ultimatepp/bazaar/plugin/gdal/frmts/idrisi/IdrisiDataset.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

3361 lines
114 KiB
C++

/*****************************************************************************
* $Id: IdrisiDataset.cpp 27942 2014-11-11 00:57:41Z rouault $
*
* Project: Idrisi Raster Image File Driver
* Purpose: Read/write Idrisi Raster Image Format RST
* Author: Ivan Lucena, [lucena_ivan at hotmail.com]
*
* Revised by Hongmei Zhu, February, 2013
* honzhu@clarku.edu
* Clark Labs/Clark University
*
******************************************************************************
* Copyright( c ) 2006, Ivan Lucena
* Copyright (c) 2007-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 "cpl_conv.h"
#include "cpl_string.h"
#include "cpl_csv.h"
#include "ogr_spatialref.h"
#include "gdal_pam.h"
#include "gdal_alg.h"
#include "gdal_rat.h"
#include "idrisi.h"
CPL_CVSID( "$Id: IdrisiDataset.cpp 27942 2014-11-11 00:57:41Z rouault $" );
CPL_C_START
void GDALRegister_IDRISI( void);
CPL_C_END
#ifdef WIN32
#define PATHDELIM '\\'
#else
#define PATHDELIM '/'
#endif
//----- Safe numeric conversion, NULL as zero
#define atoi_nz(s) (s == NULL ? (int) 0 : atoi(s))
#define CPLAtof_nz(s) (s == NULL ? (double) 0.0 : CPLAtof(s))
//----- file extensions:
#define extRST "rst"
#define extRDC "rdc"
#define extSMP "smp"
#define extREF "ref"
#define extRSTu "RST"
#define extRDCu "RDC"
#define extSMPu "SMP"
#define extREFu "REF"
//----- field names on rdc file:
#define rdcFILE_FORMAT "file format "
#define rdcFILE_TITLE "file title "
#define rdcDATA_TYPE "data type "
#define rdcFILE_TYPE "file type "
#define rdcCOLUMNS "columns "
#define rdcROWS "rows "
#define rdcREF_SYSTEM "ref. system "
#define rdcREF_UNITS "ref. units "
#define rdcUNIT_DIST "unit dist. "
#define rdcMIN_X "min. X "
#define rdcMAX_X "max. X "
#define rdcMIN_Y "min. Y "
#define rdcMAX_Y "max. Y "
#define rdcPOSN_ERROR "pos'n error "
#define rdcRESOLUTION "resolution "
#define rdcMIN_VALUE "min. value "
#define rdcMAX_VALUE "max. value "
#define rdcDISPLAY_MIN "display min "
#define rdcDISPLAY_MAX "display max "
#define rdcVALUE_UNITS "value units "
#define rdcVALUE_ERROR "value error "
#define rdcFLAG_VALUE "flag value "
#define rdcFLAG_DEFN "flag def'n "
#define rdcFLAG_DEFN2 "flag def`n "
#define rdcLEGEND_CATS "legend cats "
#define rdcLINEAGES "lineage "
#define rdcCOMMENTS "comment "
#define rdcCODE_N "code %6d "
//----- ".ref" file field names:
#define refREF_SYSTEM "ref. system "
#define refREF_SYSTEM2 "ref.system "
#define refPROJECTION "projection "
#define refDATUM "datum "
#define refDELTA_WGS84 "delta WGS84 "
#define refELLIPSOID "ellipsoid "
#define refMAJOR_SAX "major s-ax "
#define refMINOR_SAX "minor s-ax "
#define refORIGIN_LONG "origin long "
#define refORIGIN_LAT "origin lat "
#define refORIGIN_X "origin X "
#define refORIGIN_Y "origin Y "
#define refSCALE_FAC "scale fac "
#define refUNITS "units "
#define refPARAMETERS "parameters "
#define refSTANDL_1 "stand ln 1 "
#define refSTANDL_2 "stand ln 2 "
//----- standard values:
#define rstVERSION "Idrisi Raster A.1"
#define rstBYTE "byte"
#define rstINTEGER "integer"
#define rstREAL "real"
#define rstRGB24 "rgb24"
#define rstDEGREE "deg"
#define rstMETER "m"
#define rstLATLONG "latlong"
#define rstLATLONG2 "lat/long"
#define rstPLANE "plane"
#define rstUTM "utm-%d%c"
#define rstSPC "spc%2d%2s%d"
//----- palette file( .smp ) header size:
#define smpHEADERSIZE 18
//----- check if file exists:
bool FileExists( const char *pszPath );
//----- Reference Table
struct ReferenceTab {
int nCode;
const char *pszName;
};
//----- USA State's reference table to USGS PCS Code
static const ReferenceTab aoUSStateTable[] = {
{101, "al"},
{201, "az"},
{301, "ar"},
{401, "ca"},
{501, "co"},
{600, "ct"},
{700, "de"},
{901, "fl"},
{1001, "ga"},
{1101, "id"},
{1201, "il"},
{1301, "in"},
{1401, "ia"},
{1501, "ks"},
{1601, "ky"},
{1701, "la"},
{1801, "me"},
{1900, "md"},
{2001, "ma"},
{2111, "mi"},
{2201, "mn"},
{2301, "ms"},
{2401, "mo"},
{2500, "mt"},
{2600, "ne"},
{2701, "nv"},
{2800, "nh"},
{2900, "nj"},
{3001, "nm"},
{3101, "ny"},
{3200, "nc"},
{3301, "nd"},
{3401, "oh"},
{3501, "ok"},
{3601, "or"},
{3701, "pa"},
{3800, "ri"},
{3900, "sc"},
{4001, "sd"},
{4100, "tn"},
{4201, "tx"},
{4301, "ut"},
{4400, "vt"},
{4501, "va"},
{4601, "wa"},
{4701, "wv"},
{4801, "wv"},
{4901, "wy"},
{5001, "ak"},
{5101, "hi"},
{5200, "pr"}
};
//---- The origin table for USA State Plane Systems
struct OriginTab83 {
double longitude;
double latitude;
const char *spcs;
};
#define ORIGIN_COUNT 148
//---- USA State plane coordinate system in IDRISI
static const OriginTab83 SPCS83Origin[] = {
{85.83, 30.50, "SPC83AL1"},
{87.50, 30.00, "SPC83AL2"},
{176.00, 51.00, "SPC83AK0"},
{142.00, 54.00, "SPC83AK2"},
{146.00, 54.00, "SPC83AK3"},
{150.00, 54.00, "SPC83AK4"},
{154.00, 54.00, "SPC83AK5"},
{158.00, 54.00, "SPC83AK6"},
{162.00, 54.00, "SPC83AK7"},
{166.00, 54.00, "SPC83AK8"},
{170.00, 54.00, "SPC83AK9"},
{110.17, 31.00, "SPC83AZ1"},
{111.92, 31.00, "SPC83AZ2"},
{113.75, 31.00, "SPC83AZ3"},
{92.00, 34.33, "SPC83AR1"},
{92.00, 32.67, "SPC83AR2"},
{122.00, 39.33, "SPC83CA1"},
{122.00, 37.67, "SPC83CA2"},
{120.50, 36.50, "SPC83CA3"},
{119.00, 35.33, "SPC83CA4"},
{118.00, 33.50, "SPC83CA5"},
{116.25, 32.17, "SPC83CA6"},
{105.50, 39.33, "SPC83CO1"},
{105.50, 37.83, "SPC83CO2"},
{105.50, 36.67, "SPC83CO3"},
{72.75, 40.83, "SPC83CT1"},
{75.42, 38.00, "SPC83DE1"},
{81.00, 24.33, "SPC83FL1"},
{82.00, 24.33, "SPC83FL2"},
{84.50, 29.00, "SPC83FL3"},
{82.17, 30.00, "SPC83GA1"},
{84.17, 30.00, "SPC83GA2"},
{155.50, 18.83, "SPC83HI1"},
{156.67, 20.33, "SPC83HI2"},
{158.00, 21.17, "SPC83HI3"},
{159.50, 21.83, "SPC83HI4"},
{160.17, 21.67, "SPC83HI5"},
{112.17, 41.67, "SPC83ID1"},
{114.00, 41.67, "SPC83ID2"},
{115.75, 41.67, "SPC83ID3"},
{88.33, 36.67, "SPC83IL1"},
{90.17, 36.67, "SPC83IL1"},
{85.67, 37.50, "SPC83IN1"},
{87.08, 37.50, "SPC83IN2"},
{93.50, 41.50, "SPC83IA1"},
{93.50, 40.00, "SPC83IA1"},
{98.00, 38.33, "SPC83KS1"},
{98.50, 36.67, "SPC83KS2"},
{84.25, 37.50, "SPC83KY1"},
{85.75, 36.33, "SPC83KY2"},
{92.50, 30.50, "SPC83LA1"},
{91.33, 28.50, "SPC83LA2"},
{91.33, 25.50, "SPC83LA3"},
{92.50, 30.67, "SPC27LA1"},//NAD27 system
{91.33, 28.67, "SPC27LA2"},
{91.33, 25.67, "SPC27LA3"},//
{68.50, 43.67, "SPC83ME1"},
{68.50, 43.83, "SPC27ME1"},//NAD27
{70.17, 42.83, "SPC83ME2"},
{77.00, 37.67, "SPC83MD1"},//
{77.00, 37.83, "SPC27MD1"},//NAD27
{71.50, 41.00, "SPC83MA1"},
{70.50, 41.00, "SPC83MA2"},
{87.00, 44.78, "SPC83MI1"},
{84.37, 43.32, "SPC83MI2"},
{84.37, 41.50, "SPC83MI3"},
{84.33, 43.32, "SPC27MI2"},//NAD27 L
{84.33, 41.50, "SPC27MI3"},//NAD27 L
{83.67, 41.50, "SPC27MI4"},//NAD27 TM
{85.75, 41.50, "SPC27MI5"},//NAD27 TM
{88.75, 41.50, "SPC27MI6"},//NAD27 TM
{93.10, 46.50, "SPC83MN1"},
{94.25, 45.00, "SPC83MN2"},
{94.00, 43.00, "SPC83MN3"},
{88.83, 29.50, "SPC83MS1"},
{90.33, 29.50, "SPC83MS2"},
{88.83, 29.67, "SPC83MS1"},//NAD27
{90.33, 30.50, "SPC83MS2"},//
{90.50, 35.83, "SPC83MO1"},
{92.50, 35.83, "SPC83MO2"},
{94.50, 36.17, "SPC83MO3"},
{109.50, 44.25, "SPC83MT1"},
{109.50, 47.00, "SPC27MT1"},//NAD27
{109.50, 45.83, "SPC27MT2"},
{109.50, 44.00, "SPC27MT3"},//
{100.00, 39.83, "SPC83NE1"},
{115.58, 34.75, "SPC83NV1"},
{116.67, 34.75, "SPC83NV2"},
{118.58, 34.75, "SPC83NV3"},
{71.67, 42.50, "SPC83NH1"},
{74.50, 38.83, "SPC83NJ1"},
{74.67, 38.83, "SPC27NJ1"},//NAD27
{104.33, 31.00, "SPC83NM1"},
{106.25, 31.00, "SPC83NM2"},
{107.83, 31.00, "SPC83NM3"},
{74.50, 38.83, "SPC83NY1"},
{76.58, 40.00, "SPC83NY2"},
{78.58, 40.00, "SPC83NY3"},
{74.00, 40.17, "SPC83NY4"},
{74.33, 40.00, "SPC27NY1"},//NAD27
{74.00, 40.50, "SPC27NY4"},//
{79.00, 33.75, "SPC83NC1"},
{100.50, 47.00, "SPC83ND1"},
{100.50, 45.67, "SPC83ND2"},
{82.50, 39.67, "SPC83OH1"},
{82.50, 38.00, "SPC83OH2"},
{98.00, 35.00, "SPC83OK1"},
{98.00, 33.33, "SPC83OK2"},
{120.50, 43.67, "SPC83OR1"},
{120.50, 41.67, "SPC83OR2"},
{77.75, 40.17, "SPC83PA1"},
{77.75, 39.33, "SPC83PA2"},
{71.50, 41.08, "SPC83RI1"},
{81.00, 31.83, "SPC83SC1"},
{81.00, 33.00, "SPC27SC1"},//NAD27
{81.00, 31.83, "SPC27SC2"},//NAD27
{100.00, 43.83, "SPC83SD1"},
{100.33, 42.33, "SPC83SD2"},
{86.00, 34.33, "SPC83TN1"},
{86.00, 34.67, "SPC27TN1"},//NAD27
{101.50, 34.00, "SPC83TX1"},//
{98.50, 31.67, "SPC83TX2"},
{100.33, 29.67, "SPC83TX3"},
{99.00, 27.83, "SPC83TX4"},
{98.50, 25.67, "SPC83TX5"},
{97.50, 31.67, "SPC27TX2"},//NAD27
{111.50, 40.33, "SPC83UT1"},
{111.50, 38.33, "SPC83UT2"},
{111.50, 36.67, "SPC83UT3"},
{72.50, 42.50, "SPC83VT1"},
{78.50, 37.67, "SPC83VA1"},
{78.50, 36.33, "SPC83VA2"},
{120.83, 47.00, "SPC83WA1"},
{120.50, 45.33, "SPC83WA2"},
{79.50, 38.50, "SPC83WV1"},
{81.00, 37.00, "SPC83WV2"},
{90.00, 45.17, "SPC83WI1"},
{90.00, 43.83, "SPC83WI2"},
{90.00, 42.00, "SPC83WI3"},
{105.17, 40.50, "SPC83WY1"},
{107.33, 40.50, "SPC83WY2"},
{108.75, 40.50, "SPC83WY3"},
{110.08, 40.50, "SPC83WY4"},
{105.17, 40.67, "SPC27WY1"},//NAD27
{105.33, 40.67, "SPC27WY2"},
{108.75, 40.67, "SPC27WY3"},
{110.08, 40.67, "SPC27WY4"},//
{66.43, 17.83, "SPC83PR1"}
};
//Get IDRISI State Plane name by origin
char *GetSpcs(double dfLon, double dfLat);
//change NAD from 83 to 27
void NAD83to27( char *pszOutRef, char *pszInRef);
#define US_STATE_COUNT ( sizeof( aoUSStateTable ) / sizeof( ReferenceTab ) )
//----- Get the Code of a US State
int GetStateCode ( const char *pszState );
//----- Get the state name of a Code
const char *GetStateName( int nCode );
//----- Conversion Table definition
struct ConvertionTab {
const char *pszName;
int nDefaultI;
int nDefaultG;
double dfConv;
};
//----- Linear Unit Conversion Table
static const ConvertionTab aoLinearUnitsConv[] = {
{"m", /* 0 */ 0, 1, 1.0},
{SRS_UL_METER, /* 1 */ 0, 1, 1.0},
{"meters", /* 2 */ 0, 1, 1.0},
{"metre", /* 3 */ 0, 1, 1.0},
{"ft", /* 4 */ 4, 5, 0.3048},
{SRS_UL_FOOT, /* 5 */ 4, 5, 0.3048},
{"feet", /* 6 */ 4, 5, 0.3048},
{"foot_us", /* 7 */ 4, 5, 0.3048006},
{"u.s. foot", /* 8 */ 4, 5, 0.3048006},
{"mi", /* 9 */ 9, 10, 1612.9},
{"mile", /* 10 */ 9, 10, 1612.9},
{"miles", /* 11 */ 9, 10, 1612.9},
{"km", /* 12 */ 12, 13, 1000.0},
{"kilometers", /* 13 */ 12, 13, 1000.0},
{"kilometer", /* 14 */ 12, 13, 1000.0},
{"kilometre", /* 15 */ 12, 13, 1000.0},
{"deg", /* 16 */ 16, 17, 0.0},
{SRS_UA_DEGREE, /* 17 */ 16, 17, 0.0},
{"degrees", /* 18 */ 16, 17, 0.0},
{"rad", /* 19 */ 19, 20, 0.0},
{SRS_UA_RADIAN, /* 20 */ 19, 20, 0.0},
{"radians", /* 21 */ 19, 20, 0.0}
};
#define LINEAR_UNITS_COUNT (sizeof(aoLinearUnitsConv) / sizeof(ConvertionTab))
//----- Get the index of a given linear unit
int GetUnitIndex( const char *pszUnitName );
//----- Get the defaut name
char *GetUnitDefault( const char *pszUnitName, const char *pszToMeter = NULL );
//----- Get the "to meter"
int GetToMeterIndex( const char *pszToMeter );
//----- CSLSaveCRLF
int SaveAsCRLF(char **papszStrList, const char *pszFname);
//----- Classes pre-definition:
class IdrisiDataset;
class IdrisiRasterBand;
// ----------------------------------------------------------------------------
// Idrisi GDALDataset
// ----------------------------------------------------------------------------
class IdrisiDataset : public GDALPamDataset
{
friend class IdrisiRasterBand;
private:
VSILFILE *fp;
char *pszFilename;
char *pszDocFilename;
char **papszRDC;
double adfGeoTransform[6];
char *pszProjection;
char **papszCategories;
char *pszUnitType;
//move GeoReference2Wkt() into header file
CPLErr Wkt2GeoReference( const char *pszProjString,
char **pszRefSystem,
char **pszRefUnit );
protected:
GDALColorTable *poColorTable;
public:
IdrisiDataset();
~IdrisiDataset();
static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
static GDALDataset *Create( const char *pszFilename,
int nXSize,
int nYSize,
int nBands,
GDALDataType eType,
char **papszOptions );
static GDALDataset *CreateCopy( const char *pszFilename,
GDALDataset *poSrcDS,
int bStrict,
char **papszOptions,
GDALProgressFunc pfnProgress,
void * pProgressData );
virtual char **GetFileList(void);
virtual CPLErr GetGeoTransform( double *padfTransform );
virtual CPLErr SetGeoTransform( double *padfTransform );
virtual const char *GetProjectionRef( void );
virtual CPLErr SetProjection( const char *pszProjString );
};
// ----------------------------------------------------------------------------
// Idrisi GDALPamRasterBand
// ----------------------------------------------------------------------------
class IdrisiRasterBand : public GDALPamRasterBand
{
friend class IdrisiDataset;
GDALRasterAttributeTable *poDefaultRAT;
private:
int nRecordSize;
GByte *pabyScanLine;
public:
IdrisiRasterBand( IdrisiDataset *poDS,
int nBand,
GDALDataType eDataType );
~IdrisiRasterBand();
virtual double GetNoDataValue( int *pbSuccess = NULL );
virtual double GetMinimum( int *pbSuccess = NULL );
virtual double GetMaximum( int *pbSuccess = NULL );
virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage );
virtual GDALColorTable *GetColorTable();
virtual GDALColorInterp GetColorInterpretation();
virtual char **GetCategoryNames();
virtual const char *GetUnitType();
virtual CPLErr SetCategoryNames( char **papszCategoryNames );
virtual CPLErr SetNoDataValue( double dfNoDataValue );
virtual CPLErr SetColorTable( GDALColorTable *poColorTable );
virtual CPLErr SetUnitType( const char *pszUnitType );
virtual CPLErr SetStatistics( double dfMin, double dfMax,
double dfMean, double dfStdDev );
CPLErr SetMinMax( double dfMin, double dfMax );
virtual GDALRasterAttributeTable *GetDefaultRAT();
virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
float fMaximum;
float fMinimum;
bool bFirstVal;
};
// ------------------------------------------------------------------------ //
// Implementation of IdrisiDataset //
// ------------------------------------------------------------------------ //
/************************************************************************/
/* IdrisiDataset() */
/************************************************************************/
IdrisiDataset::IdrisiDataset()
{
pszFilename = NULL;
fp = NULL;
papszRDC = NULL;
pszDocFilename = NULL;
pszProjection = NULL;
poColorTable = new GDALColorTable();
papszCategories = NULL;
pszUnitType = NULL;
adfGeoTransform[0] = 0.0;
adfGeoTransform[1] = 1.0;
adfGeoTransform[2] = 0.0;
adfGeoTransform[3] = 0.0;
adfGeoTransform[4] = 0.0;
adfGeoTransform[5] = 1.0;
}
/************************************************************************/
/* ~IdrisiDataset() */
/************************************************************************/
IdrisiDataset::~IdrisiDataset()
{
FlushCache();
if( papszRDC != NULL )
{
int i;
//int bSuccessMin = FALSE;
//int bSuccessMax = FALSE;
double dfMin = 0.0;
double dfMax = 0.0;
double dfMean = 0.0;
double dfStdDev = 0.0;
for( i = 0; i < nBands; i++ )
{
IdrisiRasterBand *poBand = (IdrisiRasterBand*) GetRasterBand( i + 1 );
poBand->ComputeStatistics( false, &dfMin, &dfMax, &dfMean, &dfStdDev, NULL, NULL);
/*
dfMin = poBand->GetMinimum( &bSuccessMin );
dfMax = poBand->GetMaximum( &bSuccessMax );
if( ! ( bSuccessMin && bSuccessMax ) )
{
poBand->GetStatistics( false, true, &dfMin, &dfMax, NULL, NULL );
}
*/
poBand->SetMinMax( dfMin, dfMax);
}
if( eAccess == GA_Update )
{
CSLSetNameValueSeparator( papszRDC, ": " );
SaveAsCRLF( papszRDC, pszDocFilename );
}
CSLDestroy( papszRDC );
}
if( poColorTable )
{
delete poColorTable;
}
CPLFree( pszFilename );
CPLFree( pszDocFilename );
CPLFree( pszProjection );
CSLDestroy( papszCategories );
CPLFree( pszUnitType );
if( fp != NULL )
VSIFCloseL( fp );
}
/************************************************************************/
/* Open() */
/************************************************************************/
GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
{
if( ( poOpenInfo->fpL == NULL ) || (EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), extRST ) == FALSE ))//modified
return NULL;
// --------------------------------------------------------------------
// Check the documentation file .rdc
// --------------------------------------------------------------------
const char *pszLDocFilename = CPLResetExtension( poOpenInfo->pszFilename, extRDC );
if( ! FileExists( pszLDocFilename ) )
{
pszLDocFilename = CPLResetExtension( poOpenInfo->pszFilename, extRDCu );
if( ! FileExists( pszLDocFilename ) )
{
return NULL;
}
}
char **papszLRDC = CSLLoad( pszLDocFilename );
CSLSetNameValueSeparator( papszLRDC, ":" );
const char *pszVersion = CSLFetchNameValue( papszLRDC, rdcFILE_FORMAT );
if( pszVersion == NULL || !EQUAL( pszVersion, rstVERSION ) )
{
CSLDestroy( papszLRDC );
return NULL;
}
// --------------------------------------------------------------------
// Create a corresponding GDALDataset
// --------------------------------------------------------------------
IdrisiDataset *poDS;
poDS = new IdrisiDataset();
poDS->eAccess = poOpenInfo->eAccess;
poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename );
if( poOpenInfo->eAccess == GA_ReadOnly )
{
poDS->fp = VSIFOpenL( poDS->pszFilename, "rb" );
}
else
{
poDS->fp = VSIFOpenL( poDS->pszFilename, "r+b" );
}
if( poDS->fp == NULL )
{
CSLDestroy( papszLRDC );
delete poDS;
return NULL;
}
poDS->pszDocFilename = CPLStrdup( pszLDocFilename );
poDS->papszRDC = CSLDuplicate( papszLRDC );
CSLDestroy( papszLRDC );
// --------------------------------------------------------------------
// Load information from rdc
// --------------------------------------------------------------------
poDS->nRasterXSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcCOLUMNS ) );
poDS->nRasterYSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcROWS ) );
// --------------------------------------------------------------------
// Create band information
// --------------------------------------------------------------------
const char *pszDataType = CSLFetchNameValue( poDS->papszRDC, rdcDATA_TYPE );
if( pszDataType == NULL )
{
delete poDS;
return NULL;
}
if( EQUAL( pszDataType, rstBYTE ) )
{
poDS->nBands = 1;
poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Byte ) );
}
else if( EQUAL( pszDataType, rstINTEGER ) )
{
poDS->nBands = 1;
poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Int16 ) );
}
else if( EQUAL( pszDataType, rstREAL ) )
{
poDS->nBands = 1;
poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Float32 ) );
}
else if( EQUAL( pszDataType, rstRGB24 ) )
{
poDS->nBands = 3;
poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Byte ) );
poDS->SetBand( 2, new IdrisiRasterBand( poDS, 2, GDT_Byte ) );
poDS->SetBand( 3, new IdrisiRasterBand( poDS, 3, GDT_Byte ) );
}
else
{
CPLError(CE_Failure, CPLE_AppDefined,
"Unknown data type : %s", pszDataType);
delete poDS;
return NULL;
}
int i;
for(i=0;i<poDS->nBands;i++)
{
IdrisiRasterBand* band = (IdrisiRasterBand*) poDS->GetRasterBand(i+1);
if (band->pabyScanLine == NULL)
{
delete poDS;
return NULL;
}
}
// --------------------------------------------------------------------
// Load the transformation matrix
// --------------------------------------------------------------------
const char *pszMinX = CSLFetchNameValue( poDS->papszRDC, rdcMIN_X );
const char *pszMaxX = CSLFetchNameValue( poDS->papszRDC, rdcMAX_X );
const char *pszMinY = CSLFetchNameValue( poDS->papszRDC, rdcMIN_Y );
const char *pszMaxY = CSLFetchNameValue( poDS->papszRDC, rdcMAX_Y );
const char *pszUnit = CSLFetchNameValue( poDS->papszRDC, rdcUNIT_DIST );
if( pszMinX != NULL && strlen( pszMinX ) > 0 &&
pszMaxX != NULL && strlen( pszMaxX ) > 0 &&
pszMinY != NULL && strlen( pszMinY ) > 0 &&
pszMaxY != NULL && strlen( pszMaxY ) > 0 &&
pszUnit != NULL && strlen( pszUnit ) > 0 )
{
double dfMinX, dfMaxX, dfMinY, dfMaxY, dfUnit, dfXPixSz, dfYPixSz;
dfMinX = CPLAtof_nz( pszMinX );
dfMaxX = CPLAtof_nz( pszMaxX );
dfMinY = CPLAtof_nz( pszMinY );
dfMaxY = CPLAtof_nz( pszMaxY );
dfUnit = CPLAtof_nz( pszUnit );
dfMinX = dfMinX * dfUnit;
dfMaxX = dfMaxX * dfUnit;
dfMinY = dfMinY * dfUnit;
dfMaxY = dfMaxY * dfUnit;
dfYPixSz = ( dfMinY - dfMaxY ) / poDS->nRasterYSize;
dfXPixSz = ( dfMaxX - dfMinX ) / poDS->nRasterXSize;
poDS->adfGeoTransform[0] = dfMinX;
poDS->adfGeoTransform[1] = dfXPixSz;
poDS->adfGeoTransform[2] = 0.0;
poDS->adfGeoTransform[3] = dfMaxY;
poDS->adfGeoTransform[4] = 0.0;
poDS->adfGeoTransform[5] = dfYPixSz;
}
// --------------------------------------------------------------------
// Set Color Table in the presence of a smp file
// --------------------------------------------------------------------
if( poDS->nBands != 3 )
{
const char *pszSMPFilename = CPLResetExtension( poDS->pszFilename, extSMP );
VSILFILE *fpSMP;
if( ( fpSMP = VSIFOpenL( pszSMPFilename, "rb" ) ) != NULL )
{
int dfMaxValue = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcMAX_VALUE ) );
int nCatCount = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcLEGEND_CATS ) );
if( nCatCount == 0 )
dfMaxValue = 255;
VSIFSeekL( fpSMP, smpHEADERSIZE, SEEK_SET );
GDALColorEntry oEntry;
unsigned char aucRGB[3];
int i = 0;
while( ( VSIFReadL( &aucRGB, sizeof( aucRGB ), 1, fpSMP ) ) &&( i <= dfMaxValue ) )
{
oEntry.c1 = (short) aucRGB[0];
oEntry.c2 = (short) aucRGB[1];
oEntry.c3 = (short) aucRGB[2];
oEntry.c4 = (short) 255;
poDS->poColorTable->SetColorEntry( i, &oEntry );
i++;
}
VSIFCloseL( fpSMP );
}
}
// --------------------------------------------------------------------
// Check for Unit Type
// --------------------------------------------------------------------
const char *pszValueUnit = CSLFetchNameValue( poDS->papszRDC, rdcVALUE_UNITS );
if( pszValueUnit == NULL )
poDS->pszUnitType = CPLStrdup( "unspecified" );
else
{
if( EQUALN( pszValueUnit, "meter", 4 ) )
{
poDS->pszUnitType = CPLStrdup( "m" );
}
else if( EQUALN( pszValueUnit, "feet", 4 ) )
{
poDS->pszUnitType = CPLStrdup( "ft" );
}
else
poDS->pszUnitType = CPLStrdup( pszValueUnit );
}
// --------------------------------------------------------------------
// Check for category names.
// --------------------------------------------------------------------
int nCatCount = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcLEGEND_CATS ) );
if( nCatCount > 0 )
{
// ----------------------------------------------------------------
// Sequentialize categories names, from 0 to the last "code n"
// ----------------------------------------------------------------
int nCode = 0;
int nCount = 0;
int nLine = -1;
for( int i = 0;( i < CSLCount( poDS->papszRDC ) ) &&( nLine == -1 ); i++ )
if( EQUALN( poDS->papszRDC[i], rdcLEGEND_CATS, 11 ) )
nLine = i;//get the line where legend cats is
if( nLine > 0 )
{
sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );//asign legend cats to nCode
for( int i = 0;( i < 255 ) &&( nCount < nCatCount ); i++ )
{
if( i == nCode )
{
poDS->papszCategories =
CSLAddString( poDS->papszCategories,
CPLParseNameValue( poDS->papszRDC[nLine], NULL ) );
nCount++;
if( nCount < nCatCount )
sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );
}
else
poDS->papszCategories = CSLAddString( poDS->papszCategories, "" );
}
}
}
/* -------------------------------------------------------------------- */
/* Automatic Generated Color Table */
/* -------------------------------------------------------------------- */
if( poDS->papszCategories != NULL &&
( poDS->poColorTable->GetColorEntryCount() == 0 ) )
{
int nEntryCount = CSLCount(poDS->papszCategories);
GDALColorEntry sFromColor;
sFromColor.c1 = (short) ( 255 );
sFromColor.c2 = (short) ( 0 );
sFromColor.c3 = (short) ( 0 );
sFromColor.c4 = (short) ( 255 );
GDALColorEntry sToColor;
sToColor.c1 = (short) ( 0 );
sToColor.c2 = (short) ( 0 );
sToColor.c3 = (short) ( 255 );
sToColor.c4 = (short) ( 255 );
poDS->poColorTable->CreateColorRamp(
0, &sFromColor, ( nEntryCount - 1 ), &sToColor );
}
/* -------------------------------------------------------------------- */
/* Initialize any PAM information. */
/* -------------------------------------------------------------------- */
poDS->SetDescription( poOpenInfo->pszFilename );
poDS->TryLoadXML();
/* -------------------------------------------------------------------- */
/* Check for external overviews. */
/* -------------------------------------------------------------------- */
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
return( poDS );
}
/************************************************************************/
/* Create() */
/************************************************************************/
GDALDataset *IdrisiDataset::Create( const char *pszFilename,
int nXSize,
int nYSize,
int nBands,
GDALDataType eType,
char **papszOptions )
{
(void) papszOptions;
// --------------------------------------------------------------------
// Check input options
// --------------------------------------------------------------------
if( nBands != 1 && nBands != 3)
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create IDRISI dataset with an illegal number of bands(%d)."
" Try again by selecting a specific band if possible. \n", nBands);
return NULL;
}
if( nBands == 3 && eType != GDT_Byte )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create IDRISI dataset with an unsupported combination "
"of the number of bands(%d) and data type(%s). \n",
nBands, GDALGetDataTypeName( eType ) );
return NULL;
}
// ----------------------------------------------------------------
// Create the header file with minimun information
// ----------------------------------------------------------------
const char *pszLDataType;
switch( eType )
{
case GDT_Byte:
if( nBands == 1 )
pszLDataType = rstBYTE;
else
pszLDataType = rstRGB24;
break;
case GDT_Int16:
pszLDataType = rstINTEGER;
break;
case GDT_Float32:
pszLDataType = rstREAL;
break;
//--- process compatible data types
case (GDT_UInt16):
pszLDataType = rstINTEGER;
CPLError( CE_Warning, CPLE_AppDefined,
"This process requires a conversion from %s to signed 16-bit %s, "
"which may cause data loss.\n",
GDALGetDataTypeName( eType ), rstINTEGER);
break;
case GDT_UInt32:
pszLDataType = rstINTEGER;
CPLError( CE_Warning, CPLE_AppDefined,
"This process requires a conversion from %s to signed 16-bit %s, "
"which may cause data loss.\n",
GDALGetDataTypeName( eType ), rstINTEGER);
break;
case GDT_Int32:
pszLDataType = rstINTEGER;
CPLError( CE_Warning, CPLE_AppDefined,
"This process requires a conversion from %s to signed 16-bit %s, "
"which may cause data loss.\n",
GDALGetDataTypeName( eType ), rstINTEGER);
break;
case GDT_Float64:
pszLDataType = rstREAL;
CPLError( CE_Warning, CPLE_AppDefined,
"This process requires a conversion from %s to float 32-bit %s, "
"which may cause data loss.\n",
GDALGetDataTypeName( eType ), rstREAL);
break;
default:
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create IDRISI dataset with an illegal "
"data type(%s).\n",
GDALGetDataTypeName( eType ) );
return NULL;
};
char **papszLRDC;
papszLRDC = NULL;
papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_FORMAT, rstVERSION );
papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_TITLE, "" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcDATA_TYPE, pszLDataType );
papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_TYPE, "binary" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcCOLUMNS, CPLSPrintf( "%d", nXSize ) );
papszLRDC = CSLAddNameValue( papszLRDC, rdcROWS, CPLSPrintf( "%d", nYSize ) );
papszLRDC = CSLAddNameValue( papszLRDC, rdcREF_SYSTEM, "plane" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcREF_UNITS, "m" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcUNIT_DIST, "1" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcMIN_X, "0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcMAX_X, CPLSPrintf( "%d", nXSize ) );
papszLRDC = CSLAddNameValue( papszLRDC, rdcMIN_Y, "0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcMAX_Y, CPLSPrintf( "%d", nYSize ) );
papszLRDC = CSLAddNameValue( papszLRDC, rdcPOSN_ERROR, "unspecified" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcRESOLUTION, "1.0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcMIN_VALUE, "0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcMAX_VALUE, "0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcDISPLAY_MIN, "0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcDISPLAY_MAX, "0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcVALUE_UNITS, "unspecified" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcVALUE_ERROR, "unspecified" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcFLAG_VALUE, "none" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcFLAG_DEFN, "none" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcLEGEND_CATS, "0" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcLINEAGES, "" );
papszLRDC = CSLAddNameValue( papszLRDC, rdcCOMMENTS, "" );
const char *pszLDocFilename;
pszLDocFilename = CPLResetExtension( pszFilename, extRDC );
CSLSetNameValueSeparator( papszLRDC, ": " );
SaveAsCRLF( papszLRDC, pszLDocFilename );
CSLDestroy( papszLRDC );
// ----------------------------------------------------------------
// Create an empty data file
// ----------------------------------------------------------------
VSILFILE *fp;
fp = VSIFOpenL( pszFilename, "wb+" );
if( fp == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Attempt to create file %s' failed.\n", pszFilename );
return NULL;
}
VSIFCloseL( fp );
return (IdrisiDataset *) GDALOpen( pszFilename, GA_Update );
}
/************************************************************************/
/* CreateCopy() */
/************************************************************************/
GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
GDALDataset *poSrcDS,
int bStrict,
char **papszOptions,
GDALProgressFunc pfnProgress,
void *pProgressData )
{
if( !pfnProgress( 0.0, NULL, pProgressData ) )
return NULL;
// ------------------------------------------------------------------------
// Check number of bands
// ------------------------------------------------------------------------
if ( !( poSrcDS->GetRasterCount() == 1 ) && !( poSrcDS->GetRasterCount() == 3 ))
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create IDRISI dataset with an illegal number of bands(%d)."
" Try again by selecting a specific band if possible.\n",
poSrcDS->GetRasterCount() );
return NULL;
}
if ( ( poSrcDS->GetRasterCount() == 3 ) &&
( ( poSrcDS->GetRasterBand( 1 )->GetRasterDataType() != GDT_Byte ) ||
( poSrcDS->GetRasterBand( 2 )->GetRasterDataType() != GDT_Byte ) ||
( poSrcDS->GetRasterBand( 3 )->GetRasterDataType() != GDT_Byte ) ) )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create IDRISI dataset with an unsupported "
"data type when there are three bands. Only BYTE allowed.\n"
"Try again by selecting a specific band to convert if possible.\n");
return NULL;
}
// ------------------------------------------------------------------------
// Check Data types
// ------------------------------------------------------------------------
int i;
for( i = 1; i <= poSrcDS->GetRasterCount(); i++ )
{
GDALDataType eType = poSrcDS->GetRasterBand( i )->GetRasterDataType();
if( bStrict )
{
if( eType != GDT_Byte &&
eType != GDT_Int16 &&
eType != GDT_Float32 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create IDRISI dataset in strict mode "
"with an illegal data type(%s).\n",
GDALGetDataTypeName( eType ) );
return NULL;
}
}
else
{
if( eType != GDT_Byte &&
eType != GDT_Int16 &&
eType != GDT_UInt16 &&
eType != GDT_UInt32 &&
eType != GDT_Int32 &&
eType != GDT_Float32 &&
eType != GDT_Float64 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to create IDRISI dataset with an illegal data type(%s).\n",
GDALGetDataTypeName( eType ) );
return NULL;
}
}
}
// --------------------------------------------------------------------
// Define data type
// --------------------------------------------------------------------
GDALRasterBand *poBand = poSrcDS->GetRasterBand( 1 );
GDALDataType eType = poBand->GetRasterDataType();
int bSuccessMin = FALSE;
int bSuccessMax = FALSE;
double dfMin;
double dfMax;
dfMin = poBand->GetMinimum( &bSuccessMin );
dfMax = poBand->GetMaximum( &bSuccessMax );
if( ! ( bSuccessMin && bSuccessMax ) )
{
poBand->GetStatistics( false, true, &dfMin, &dfMax, NULL, NULL );
}
if(!( ( eType == GDT_Byte ) ||
( eType == GDT_Int16 ) ||
( eType == GDT_Float32 ) ) )
{
if( eType == GDT_Float64 )
{
eType = GDT_Float32;
}
else
{
if( ( dfMin < (double) SHRT_MIN ) ||
( dfMax > (double) SHRT_MAX ) )
{
eType = GDT_Float32;
}
else
{
eType = GDT_Int16;
}
}
}
// --------------------------------------------------------------------
// Create the dataset
// --------------------------------------------------------------------
IdrisiDataset *poDS;
poDS = (IdrisiDataset *) IdrisiDataset::Create( pszFilename,
poSrcDS->GetRasterXSize(),
poSrcDS->GetRasterYSize(),
poSrcDS->GetRasterCount(),
eType,
papszOptions );
if( poDS == NULL )
return NULL;
// --------------------------------------------------------------------
// Copy information to the dataset
// --------------------------------------------------------------------
double adfGeoTransform[6];
if (!EQUAL(poSrcDS->GetProjectionRef(),""))
{
poSrcDS->GetGeoTransform(adfGeoTransform);
poDS->SetGeoTransform(adfGeoTransform);
poDS->SetProjection( poSrcDS->GetProjectionRef() );
}
// --------------------------------------------------------------------
// Copy information to the raster band(s)
// --------------------------------------------------------------------
GDALRasterBand *poSrcBand;
int bHasNoDataValue;
double dfNoDataValue;
for( i = 1; i <= poDS->nBands; i++ )
{
poSrcBand = poSrcDS->GetRasterBand( i );
IdrisiRasterBand* poDstBand = (IdrisiRasterBand*) poDS->GetRasterBand( i );
if( poDS->nBands == 1 )
{
poDstBand->SetUnitType( poSrcBand->GetUnitType() );
poDstBand->SetColorTable( poSrcBand->GetColorTable() );
poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
const GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
if( poRAT != NULL )
{
poDstBand->SetDefaultRAT( poRAT );
}
}
dfMin = poSrcBand->GetMinimum( NULL );
dfMax = poSrcBand->GetMaximum( NULL );
poDstBand->SetMinMax( dfMin, dfMax );
dfNoDataValue = poSrcBand->GetNoDataValue( &bHasNoDataValue );
if( bHasNoDataValue )
poDstBand->SetNoDataValue( dfNoDataValue );
}
// --------------------------------------------------------------------
// Copy image data
// --------------------------------------------------------------------
GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
(GDALDatasetH) poDS, NULL,
pfnProgress, pProgressData );
// --------------------------------------------------------------------
// Finalize
// --------------------------------------------------------------------
poDS->FlushCache();
return poDS;
}
/************************************************************************/
/* GetFileList() */
/************************************************************************/
char **IdrisiDataset::GetFileList()
{
char **papszFileList = GDALPamDataset::GetFileList();
const char *pszAssociated;
// --------------------------------------------------------------------
// Symbol table file
// --------------------------------------------------------------------
pszAssociated = CPLResetExtension( pszFilename, extSMP );
if( FileExists( pszAssociated ) )
{
papszFileList = CSLAddString( papszFileList, pszAssociated );
}
else
{
pszAssociated = CPLResetExtension( pszFilename, extSMPu );
if( FileExists( pszAssociated ) )
{
papszFileList = CSLAddString( papszFileList, pszAssociated );
}
}
// --------------------------------------------------------------------
// Documentation file
// --------------------------------------------------------------------
pszAssociated = CPLResetExtension( pszFilename, extRDC );
if( FileExists( pszAssociated ) )
{
papszFileList = CSLAddString( papszFileList, pszAssociated );
}
else
{
pszAssociated = CPLResetExtension( pszFilename, extRDCu );
if( FileExists( pszAssociated ) )
{
papszFileList = CSLAddString( papszFileList, pszAssociated );
}
}
// --------------------------------------------------------------------
// Reference file
// --------------------------------------------------------------------
pszAssociated = CPLResetExtension( pszFilename, extREF );
if( FileExists( pszAssociated ) )
{
papszFileList = CSLAddString( papszFileList, pszAssociated );
}
else
{
pszAssociated = CPLResetExtension( pszFilename, extREFu );
if( FileExists( pszAssociated ) )
{
papszFileList = CSLAddString( papszFileList, pszAssociated );
}
}
return papszFileList;
}
/************************************************************************/
/* GetGeoTransform() */
/************************************************************************/
CPLErr IdrisiDataset::GetGeoTransform( double * padfTransform )
{
if( GDALPamDataset::GetGeoTransform( padfTransform ) != CE_None )
{
memcpy( padfTransform, adfGeoTransform, sizeof( double ) * 6 );
/*
if( adfGeoTransform[0] == 0.0
&& adfGeoTransform[1] == 1.0
&& adfGeoTransform[2] == 0.0
&& adfGeoTransform[3] == 0.0
&& adfGeoTransform[4] == 0.0
&& adfGeoTransform[5] == 1.0 )
return CE_Failure;
*/
}
return CE_None;
}
/************************************************************************/
/* SetGeoTransform() */
/************************************************************************/
CPLErr IdrisiDataset::SetGeoTransform( double * padfTransform )
{
if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to set rotated geotransform on Idrisi Raster file.\n"
"Idrisi Raster does not support rotation.\n" );
return CE_Failure;
}
// --------------------------------------------------------------------
// Update the .rdc file
// --------------------------------------------------------------------
double dfMinX, dfMaxX, dfMinY, dfMaxY, dfXPixSz, dfYPixSz;
dfXPixSz = padfTransform[1];
dfYPixSz = padfTransform[5];
dfMinX = padfTransform[0];
dfMaxX = ( dfXPixSz * nRasterXSize ) + dfMinX;
if( dfYPixSz < 0 )
{
dfMaxY = padfTransform[3];
dfMinY = ( dfYPixSz * nRasterYSize ) + padfTransform[3];
}
else
{
dfMaxY = ( dfYPixSz * nRasterYSize ) + padfTransform[3];
dfMinY = padfTransform[3];
}
papszRDC = CSLSetNameValue( papszRDC, rdcMIN_X, CPLSPrintf( "%.7f", dfMinX ) );
papszRDC = CSLSetNameValue( papszRDC, rdcMAX_X, CPLSPrintf( "%.7f", dfMaxX ) );
papszRDC = CSLSetNameValue( papszRDC, rdcMIN_Y, CPLSPrintf( "%.7f", dfMinY ) );
papszRDC = CSLSetNameValue( papszRDC, rdcMAX_Y, CPLSPrintf( "%.7f", dfMaxY ) );
papszRDC = CSLSetNameValue( papszRDC, rdcRESOLUTION, CPLSPrintf( "%.7f", fabs( dfYPixSz ) ) );
// --------------------------------------------------------------------
// Update the Dataset attribute
// --------------------------------------------------------------------
memcpy( adfGeoTransform, padfTransform, sizeof( double ) * 6 );
return CE_None;
}
/************************************************************************/
/* GetProjectionRef() */
/************************************************************************/
const char *IdrisiDataset::GetProjectionRef( void )
{
const char *pszPamSRS = GDALPamDataset::GetProjectionRef();
if( pszPamSRS != NULL && strlen( pszPamSRS ) > 0 )
return pszPamSRS;
if( pszProjection == NULL )
{
const char *pszRefSystem = CSLFetchNameValue( papszRDC, rdcREF_SYSTEM );
const char *pszRefUnit = CSLFetchNameValue( papszRDC, rdcREF_UNITS );
if (pszRefSystem != NULL && pszRefUnit != NULL)
IdrisiGeoReference2Wkt( pszFilename, pszRefSystem, pszRefUnit, &pszProjection );
else
pszProjection = CPLStrdup("");
}
return pszProjection;
}
/************************************************************************/
/* SetProjection() */
/************************************************************************/
CPLErr IdrisiDataset::SetProjection( const char *pszProjString )
{
CPLFree( pszProjection );
pszProjection = CPLStrdup( pszProjString );
CPLErr eResult = CE_None;
char *pszRefSystem = NULL;
char *pszRefUnit = NULL;
eResult = Wkt2GeoReference( pszProjString, &pszRefSystem, &pszRefUnit );
papszRDC = CSLSetNameValue( papszRDC, rdcREF_SYSTEM, pszRefSystem );
papszRDC = CSLSetNameValue( papszRDC, rdcREF_UNITS, pszRefUnit );
CPLFree( pszRefSystem );
CPLFree( pszRefUnit );
return eResult;
}
/************************************************************************/
/* IdrisiRasterBand() */
/************************************************************************/
IdrisiRasterBand::IdrisiRasterBand( IdrisiDataset *poDS,
int nBand,
GDALDataType eDataType )
{
this->poDS = poDS;
this->nBand = nBand;
this->eDataType = eDataType;
this->poDefaultRAT = NULL;
this->fMinimum = 0.0;
this->fMaximum = 0.0;
this->bFirstVal = true;
// --------------------------------------------------------------------
// Set Dimension
// --------------------------------------------------------------------
nBlockYSize = 1;
nBlockXSize = poDS->GetRasterXSize();
// --------------------------------------------------------------------
// Get ready for reading and writing
// --------------------------------------------------------------------
nRecordSize = poDS->GetRasterXSize() * GDALGetDataTypeSize( eDataType ) / 8;
pabyScanLine = (GByte*) VSIMalloc2( nRecordSize, poDS->nBands );
if( pabyScanLine == NULL )
{
CPLError(CE_Failure, CPLE_OutOfMemory,
"IdrisiRasterBand::IdrisiRasterBand : Out of memory (nRasterXSize = %d)",
poDS->GetRasterXSize());
}
nRecordSize *= poDS->nBands;
}
/************************************************************************/
/* ~IdrisiRasterBand() */
/************************************************************************/
IdrisiRasterBand::~IdrisiRasterBand()
{
CPLFree( pabyScanLine );
if( poDefaultRAT )
{
delete poDefaultRAT;
}
}
/************************************************************************/
/* IReadBlock() */
/************************************************************************/
CPLErr IdrisiRasterBand::IReadBlock( int nBlockXOff,
int nBlockYOff,
void *pImage )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
if( VSIFSeekL( poGDS->fp,
vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET ) < 0 )
{
CPLError( CE_Failure, CPLE_FileIO,
"Can't seek(%s) block with X offset %d and Y offset %d.\n%s",
poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
return CE_Failure;
}
if( (int) VSIFReadL( pabyScanLine, 1, nRecordSize, poGDS->fp ) < nRecordSize )
{
CPLError( CE_Failure, CPLE_FileIO,
"Can't read(%s) block with X offset %d and Y offset %d.\n%s",
poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
return CE_Failure;
}
if( poGDS->nBands == 3 )
{
int i, j;
for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
{
( (GByte*) pImage )[i] = pabyScanLine[j];
}
}
else
{
memcpy( pImage, pabyScanLine, nRecordSize );
}
#ifdef CPL_MSB
if( eDataType == GDT_Float32 )
GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
#endif
return CE_None;
}
/************************************************************************/
/* IWriteBlock() */
/************************************************************************/
CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
int nBlockYOff,
void *pImage )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
#ifdef CPL_MSB
// Swap in input buffer if needed.
if( eDataType == GDT_Float32 )
GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
#endif
if( poGDS->nBands == 1 )
{
memcpy( pabyScanLine, pImage, nRecordSize );
}
else
{
if( nBand > 1 )
{
VSIFSeekL( poGDS->fp,
vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET );
VSIFReadL( pabyScanLine, 1, nRecordSize, poGDS->fp );
}
int i, j;
for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
{
pabyScanLine[j] = ( (GByte *) pImage )[i];
}
}
#ifdef CPL_MSB
// Swap input buffer back to original form.
if( eDataType == GDT_Float32 )
GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
#endif
VSIFSeekL( poGDS->fp, vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET );
if( (int) VSIFWriteL( pabyScanLine, 1, nRecordSize, poGDS->fp ) < nRecordSize )
{
CPLError( CE_Failure, CPLE_FileIO,
"Can't write(%s) block with X offset %d and Y offset %d.\n%s",
poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
return CE_Failure;
}
int bHasNoDataValue = FALSE;
float fNoDataValue = (float) GetNoDataValue(&bHasNoDataValue);
// --------------------------------------------------------------------
// Search for the minimum and maximum values
// --------------------------------------------------------------------
int i, j;
if( eDataType == GDT_Float32 )
{
for( i = 0; i < nBlockXSize; i++ )
{
float fVal = ((float*) pabyScanLine)[i]; //this is fine
if( !bHasNoDataValue || fVal != fNoDataValue )
{
if( bFirstVal )
{
fMinimum = fMaximum = fVal;
bFirstVal = false;
}
else
{
if( fVal < fMinimum) fMinimum = fVal;
if( fVal > fMaximum) fMaximum = fVal;
}
}
}
}
else if( eDataType == GDT_Int16 )
{
for( i = 0; i < nBlockXSize; i++ )
{
float fVal = (float) ((GInt16*) pabyScanLine)[i];
if( !bHasNoDataValue || fVal != fNoDataValue )
{
if( bFirstVal )
{
fMinimum = fMaximum = fVal;
bFirstVal = false;
}
else
{
if( fVal < fMinimum) fMinimum = fVal;
if( fVal > fMaximum) fMaximum = fVal;
}
}
}
}
else if( poGDS->nBands == 1 )
{
for( i = 0; i < nBlockXSize; i++ )
{
float fVal = (float) ((GByte*) pabyScanLine)[i];
if( !bHasNoDataValue || fVal != fNoDataValue )
{
if( bFirstVal )
{
fMinimum = fMaximum = fVal;
bFirstVal = false;
}
else
{
if( fVal < fMinimum) fMinimum = fVal;//I don't change this part, keep it as it is
if( fVal > fMaximum) fMaximum = fVal;
}
}
}
}
else
{
for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
{
float fVal = (float) ((GByte*) pabyScanLine)[j];
if( !bHasNoDataValue || fVal != fNoDataValue )
{
if( bFirstVal )
{
fMinimum = fMaximum = fVal;
bFirstVal = false;
}
else
{
if( fVal < fMinimum) fMinimum = fVal;
if( fVal > fMaximum) fMaximum = fVal;
}
}
}
}
return CE_None;
}
/************************************************************************/
/* GetMinimum() */
/************************************************************************/
double IdrisiRasterBand::GetMinimum( int *pbSuccess )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
if (CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ) == NULL)
return GDALPamRasterBand::GetMinimum(pbSuccess);
double adfMinValue[3];
CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ), "%lf %lf %lf",
&adfMinValue[0], &adfMinValue[1], &adfMinValue[2] );
if( pbSuccess )
{
*pbSuccess = true;
}
return adfMinValue[this->nBand - 1];
}
/************************************************************************/
/* GetMaximum() */
/************************************************************************/
double IdrisiRasterBand::GetMaximum( int *pbSuccess )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
if (CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ) == NULL)
return GDALPamRasterBand::GetMaximum(pbSuccess);
double adfMaxValue[3];
CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ), "%lf %lf %lf",
&adfMaxValue[0], &adfMaxValue[1], &adfMaxValue[2] );
if( pbSuccess )
{
*pbSuccess = true;
}
return adfMaxValue[this->nBand - 1];
}
/************************************************************************/
/* GetNoDataValue() */
/************************************************************************/
double IdrisiRasterBand::GetNoDataValue( int *pbSuccess )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
double dfNoData;
const char *pszFlagDefn;
if( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN ) != NULL )
pszFlagDefn = CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN );
else if( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN2 ) != NULL )
pszFlagDefn = CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN2 );
else
pszFlagDefn = CPLStrdup( "none" );
// ------------------------------------------------------------------------
// If Flag_Def is not "none", Flag_Value means "background"
// or "missing data"
// ------------------------------------------------------------------------
if( ! EQUAL( pszFlagDefn, "none" ) )
{
dfNoData = CPLAtof_nz( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_VALUE ) );
if( pbSuccess )
*pbSuccess = TRUE;
}
else
{
dfNoData = -9999.0; /* this value should be ignored */
if( pbSuccess )
*pbSuccess = FALSE;
}
return dfNoData;
}
/************************************************************************/
/* SetNoDataValue() */
/************************************************************************/
CPLErr IdrisiRasterBand::SetNoDataValue( double dfNoDataValue )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcFLAG_VALUE, CPLSPrintf( "%.7g", dfNoDataValue ) );
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcFLAG_DEFN, "missing data" );
return CE_None;
}
/************************************************************************/
/* GetColorInterpretation() */
/************************************************************************/
GDALColorInterp IdrisiRasterBand::GetColorInterpretation()
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
if( poGDS->nBands == 3 )
{
switch( nBand )
{
case 1: return GCI_BlueBand;
case 2: return GCI_GreenBand;
case 3: return GCI_RedBand;
}
}
else if( poGDS->poColorTable->GetColorEntryCount() > 0 )
{
return GCI_PaletteIndex;
}
return GCI_GrayIndex;
}
/************************************************************************/
/* GetCategoryNames() */
/************************************************************************/
char **IdrisiRasterBand::GetCategoryNames()
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
return poGDS->papszCategories;
}
/************************************************************************/
/* SetCategoryNames() */
/************************************************************************/
CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
{
int nCatCount = CSLCount( papszCategoryNames );
if( nCatCount == 0 )
return CE_None;
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
CSLDestroy( poGDS->papszCategories );
poGDS->papszCategories = CSLDuplicate( papszCategoryNames );
// ------------------------------------------------------
// Search for the "Legend cats : N" line
// ------------------------------------------------------
int i, nLine = -1;
for( i = 0;( i < CSLCount( poGDS->papszRDC ) ) &&( nLine == -1 ); i++ )
if( EQUALN( poGDS->papszRDC[i], rdcLEGEND_CATS, 12 ) )
nLine = i;
if( nLine < 0 )
return CE_None;
int nCount = atoi_nz( CSLFetchNameValue( poGDS->papszRDC, rdcLEGEND_CATS ) );
// ------------------------------------------------------
// Delte old instance of the categoty names
// ------------------------------------------------------
if( nCount > 0 )
poGDS->papszRDC = CSLRemoveStrings( poGDS->papszRDC, nLine + 1, nCount, NULL );
nCount = 0;
for( i = 0; i < nCatCount; i++ )
{
if( ( strlen( papszCategoryNames[i] ) > 0 ) )
{
poGDS->papszRDC = CSLInsertString( poGDS->papszRDC,( nLine + nCount + 1 ),
CPLSPrintf( "%s:%s", CPLSPrintf( rdcCODE_N, i ), papszCategoryNames[i] ) );
nCount++;
}
}
poGDS->papszRDC = CSLSetNameValue( poGDS->papszRDC, rdcLEGEND_CATS, CPLSPrintf( "%d", nCount ) );//this is fine
return CE_None;
}
/************************************************************************/
/* GetColorTable() */
/************************************************************************/
GDALColorTable *IdrisiRasterBand::GetColorTable()
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
if( poGDS->poColorTable->GetColorEntryCount() == 0 )
{
return NULL;
}
else
{
return poGDS->poColorTable;
}
}
/************************************************************************/
/* SetColorTable() */
/************************************************************************/
CPLErr IdrisiRasterBand::SetColorTable( GDALColorTable *poColorTable )
{
if( poColorTable == NULL )
{
return CE_None;
}
if( poColorTable->GetColorEntryCount() == 0 )
{
return CE_None;
}
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
delete poGDS->poColorTable;
poGDS->poColorTable = poColorTable->Clone();
const char *pszSMPFilename;
pszSMPFilename = CPLResetExtension( poGDS->pszFilename, extSMP );
VSILFILE *fpSMP;
if( ( fpSMP = VSIFOpenL( pszSMPFilename, "w" ) ) != NULL )
{
VSIFWriteL( "[Idrisi]", 8, 1, fpSMP );
GByte nPlatform = 1; VSIFWriteL( &nPlatform, 1, 1, fpSMP );
GByte nVersion = 11; VSIFWriteL( &nVersion, 1, 1, fpSMP );
GByte nDepth = 8; VSIFWriteL( &nDepth, 1, 1, fpSMP );
GByte nHeadSz = 18; VSIFWriteL( &nHeadSz, 1, 1, fpSMP );
GUInt16 nCount = 255; VSIFWriteL( &nCount, 2, 1, fpSMP );
GUInt16 nMix = 0; VSIFWriteL( &nMix, 2, 1, fpSMP );
GUInt16 nMax = 255; VSIFWriteL( &nMax, 2, 1, fpSMP );
GDALColorEntry oEntry;
GByte aucRGB[3];
int i;
for( i = 0; i < poColorTable->GetColorEntryCount(); i++ )
{
poColorTable->GetColorEntryAsRGB( i, &oEntry );
aucRGB[0] = (GByte) oEntry.c1;
aucRGB[1] = (GByte) oEntry.c2;
aucRGB[2] = (GByte) oEntry.c3;
VSIFWriteL( &aucRGB, 3, 1, fpSMP );
}
/* smp files always have 256 occurences */
for( i = poColorTable->GetColorEntryCount(); i <= 255; i++ )
{
poColorTable->GetColorEntryAsRGB( i, &oEntry );
aucRGB[0] = (GByte) 0;
aucRGB[1] = (GByte) 0;
aucRGB[2] = (GByte) 0;
VSIFWriteL( &aucRGB, 3, 1, fpSMP );
}
VSIFCloseL( fpSMP );
}
return CE_None;
}
/************************************************************************/
/* GetUnitType() */
/************************************************************************/
const char *IdrisiRasterBand::GetUnitType()
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
return poGDS->pszUnitType;
}
/************************************************************************/
/* SetUnitType() */
/************************************************************************/
CPLErr IdrisiRasterBand::SetUnitType( const char *pszUnitType )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
if( strlen( pszUnitType ) == 0 )
{
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcVALUE_UNITS, "unspecified" );
}
else
{
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcVALUE_UNITS, pszUnitType );
}
return CE_None;
}
/************************************************************************/
/* SetMinMax() */
/************************************************************************/
CPLErr IdrisiRasterBand::SetMinMax( double dfMin, double dfMax )
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
fMinimum = (float)dfMin;
fMaximum = (float)dfMax;
double adfMin[3] = {0.0, 0.0, 0.0};
double adfMax[3] = {0.0, 0.0, 0.0};
if (CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ) != NULL)
CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ), "%lf %lf %lf", &adfMin[0], &adfMin[1], &adfMin[2] );
if (CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ) != NULL)
CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ), "%lf %lf %lf", &adfMax[0], &adfMax[1], &adfMax[2] );
adfMin[nBand - 1] = dfMin;
adfMax[nBand - 1] = dfMax;
if( poGDS->nBands == 3 )
{
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcMIN_VALUE, CPLSPrintf( "%.8g %.8g %.8g", adfMin[0], adfMin[1], adfMin[2] ) );
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcMAX_VALUE, CPLSPrintf( "%.8g %.8g %.8g", adfMax[0], adfMax[1], adfMax[2] ) );
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MIN, CPLSPrintf( "%.8g %.8g %.8g", adfMin[0], adfMin[1], adfMin[2] ) );
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MAX, CPLSPrintf( "%.8g %.8g %.8g", adfMax[0], adfMax[1], adfMax[2] ) );
}
else
{
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcMIN_VALUE, CPLSPrintf( "%.8g", adfMin[0] ) );
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcMAX_VALUE, CPLSPrintf( "%.8g", adfMax[0] ) );
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MIN, CPLSPrintf( "%.8g", adfMin[0] ) );
poGDS->papszRDC =
CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MAX, CPLSPrintf( "%.8g", adfMax[0] ) );
}
return CE_None;
}
/************************************************************************/
/* SetStatistics() */
/************************************************************************/
CPLErr IdrisiRasterBand::SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev )
{
SetMinMax(dfMin, dfMax);
return GDALPamRasterBand::SetStatistics(dfMin, dfMax, dfMean, dfStdDev);
}
/************************************************************************/
/* SetDefaultRAT() */
/************************************************************************/
CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
{
if( ! poRAT )
{
return CE_Failure;
}
// ----------------------------------------------------------
// Get field indecies
// ----------------------------------------------------------
int iValue = -1;
int iRed = poRAT->GetColOfUsage( GFU_Red );
int iGreen = poRAT->GetColOfUsage( GFU_Green );
int iBlue = poRAT->GetColOfUsage( GFU_Blue );
int iName = -1;
int i;
GDALColorTable *poCT = NULL;
char **papszNames = NULL;
int nFact = 1;
// ----------------------------------------------------------
// Seek for "Value" field index (AGIS standards field name)
// ----------------------------------------------------------
if( GetColorTable() == 0 || GetColorTable()->GetColorEntryCount() == 0 )
{
for( i = 0; i < poRAT->GetColumnCount(); i++ )
{
if EQUALN( "Value", poRAT->GetNameOfCol( i ), 5 )
{
iValue = i;
break;
}
}
if( iRed != -1 && iGreen != -1 && iBlue != -1 )
{
poCT = new GDALColorTable();
nFact = poRAT->GetTypeOfCol( iRed ) == GFT_Real ? 255 : 1;
}
}
// ----------------------------------------------------------
// Seek for Name field index
// ----------------------------------------------------------
if( GetCategoryNames() == 0 || CSLCount( GetCategoryNames() ) == 0 )
{
iName = poRAT->GetColOfUsage( GFU_Name );
if( iName == -1 )
{
for( i = 0; i < poRAT->GetColumnCount(); i++ )
{
if EQUALN( "Class_Name", poRAT->GetNameOfCol( i ), 10 )
{
iName = i;
break;
}
else if EQUALN( "Categor", poRAT->GetNameOfCol( i ), 7 )
{
iName = i;
break;
}
else if EQUALN( "Name", poRAT->GetNameOfCol( i ), 4 )
{
iName = i;
break;
}
}
}
/* if still can't find it use the first String column */
if( iName == -1 )
{
for( i = 0; i < poRAT->GetColumnCount(); i++ )
{
if( poRAT->GetTypeOfCol( i ) == GFT_String )
{
iName = i;
break;
}
}
}
// ----------------------------------------------------------
// Incomplete Attribute Table;
// ----------------------------------------------------------
if( iName == -1 )
{
iName = iValue;
}
}
// ----------------------------------------------------------
// Initialization
// ----------------------------------------------------------
double dRed = 0.0;
double dGreen = 0.0;
double dBlue = 0.0;
// ----------------------------------------------------------
// Load values
// ----------------------------------------------------------
GDALColorEntry sColor;
int iEntry = 0;
int iOut = 0;
int nEntryCount = poRAT->GetRowCount();
int nValue = 0;
if( iValue != -1 )
{
nValue = poRAT->GetValueAsInt( iEntry, iValue );
}
for( iOut = 0; iOut < 65535 && ( iEntry < nEntryCount ); iOut++ )
{
if( iOut == nValue )
{
if( poCT )
{
dRed = poRAT->GetValueAsDouble( iEntry, iRed );
dGreen = poRAT->GetValueAsDouble( iEntry, iGreen );
dBlue = poRAT->GetValueAsDouble( iEntry, iBlue );
sColor.c1 = (short) ( dRed * nFact );
sColor.c2 = (short) ( dGreen * nFact );
sColor.c3 = (short) ( dBlue * nFact );
sColor.c4 = (short) ( 255 / nFact );
poCT->SetColorEntry( iEntry, &sColor );
}
if( iName != -1 )
{
papszNames = CSLAddString( papszNames,
poRAT->GetValueAsString( iEntry, iName ) );
}
/* Advance on the table */
if( ( ++iEntry ) < nEntryCount )
{
if( iValue != -1 )
nValue = poRAT->GetValueAsInt( iEntry, iValue );
else
nValue = iEntry;
}
}
else if( iOut < nValue )
{
if( poCT )
{
sColor.c1 = (short) 0;
sColor.c2 = (short) 0;
sColor.c3 = (short) 0;
sColor.c4 = (short) 255;
poCT->SetColorEntry( iEntry, &sColor );
}
if( iName != -1 )
papszNames = CSLAddString( papszNames, "" );
}
}
// ----------------------------------------------------------
// Set Color Table
// ----------------------------------------------------------
if( poCT )
{
SetColorTable( poCT );
delete poCT;
}
// ----------------------------------------------------------
// Update Category Names
// ----------------------------------------------------------
if( papszNames )
{
SetCategoryNames( papszNames );
CSLDestroy( papszNames );
}
// ----------------------------------------------------------
// Update Attribute Table
// ----------------------------------------------------------
if( poDefaultRAT )
{
delete poDefaultRAT;
}
poDefaultRAT = poRAT->Clone();
return CE_None;
}
/************************************************************************/
/* GetDefaultRAT() */
/************************************************************************/
GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
{
IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
if( poGDS->papszCategories == NULL )
{
return NULL;
}
bool bHasColorTable = poGDS->poColorTable->GetColorEntryCount() > 0;
// ----------------------------------------------------------
// Create the bands Attribute Table
// ----------------------------------------------------------
if( poDefaultRAT )
{
delete poDefaultRAT;
}
poDefaultRAT = new GDALDefaultRasterAttributeTable();
// ----------------------------------------------------------
// Create (Value, Red, Green, Blue, Alpha, Class_Name) fields
// ----------------------------------------------------------
poDefaultRAT->CreateColumn( "Value", GFT_Integer, GFU_Generic );
poDefaultRAT->CreateColumn( "Value_1", GFT_Integer, GFU_MinMax );
if( bHasColorTable )
{
poDefaultRAT->CreateColumn( "Red", GFT_Integer, GFU_Red );
poDefaultRAT->CreateColumn( "Green", GFT_Integer, GFU_Green );
poDefaultRAT->CreateColumn( "Blue", GFT_Integer, GFU_Blue );
poDefaultRAT->CreateColumn( "Alpha", GFT_Integer, GFU_Alpha );
}
poDefaultRAT->CreateColumn( "Class_name", GFT_String, GFU_Name );
// ----------------------------------------------------------
// Loop throught the Category Names
// ----------------------------------------------------------
GDALColorEntry sEntry;
int iName = poDefaultRAT->GetColOfUsage( GFU_Name );
int nEntryCount = CSLCount( poGDS->papszCategories );
int iEntry = 0;
int iRows = 0;
for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
{
if EQUAL( poGDS->papszCategories[iEntry], "" )
{
continue; // Eliminate the empty ones
}
poDefaultRAT->SetRowCount( poDefaultRAT->GetRowCount() + 1 );
poDefaultRAT->SetValue( iRows, 0, iEntry );
poDefaultRAT->SetValue( iRows, 1, iEntry );
if( bHasColorTable )
{
poGDS->poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
poDefaultRAT->SetValue( iRows, 2, sEntry.c1 );
poDefaultRAT->SetValue( iRows, 3, sEntry.c2 );
poDefaultRAT->SetValue( iRows, 4, sEntry.c3 );
poDefaultRAT->SetValue( iRows, 5, sEntry.c4 );
}
poDefaultRAT->SetValue( iRows, iName, poGDS->papszCategories[iEntry] );
iRows++;
}
return poDefaultRAT;
}
/************************************************************************/
/* IdrisiGeoReference2Wkt() */
/************************************************************************/
/***
* Converts Idrisi geographic reference information to OpenGIS WKT.
*
* The Idrisi metadata file contain two fields that describe the
* geographic reference, RefSystem and RefUnit.
*
* RefSystem can contains the world "plane" or the name of a georeference
* file <refsystem>.ref that details the geographic reference
* system( coordinate system and projection parameters ). RefUnits
* indicates the unit of the image bounds.
*
* The georeference files are generally located in the product installation
* folder $IDRISIDIR\Georef, but they are first looked for in the same
* folder as the data file.
*
* If a Reference system names can be recognized by a name convention
* it will be interpreted without the need to read the georeference file.
* That includes "latlong" and all the UTM and State Plane zones.
*
* RefSystem "latlong" means that the data is not project and the coordinate
* system is WGS84. RefSystem "plane" means that the there is no coordinate
* system but the it is possible to calculate areas and distance by looking
* at the RefUnits.
*
* If the environment variable IDRISIDIR is not set and the georeference file
* need to be read then the projection string will result as unknown.
***/
CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
const char *pszRefSystem,
const char *pszRefUnits,
char **ppszProjString )
{
OGRSpatialReference oSRS;
*ppszProjString = NULL;
// ---------------------------------------------------------
// Plane
// ---------------------------------------------------------
if( EQUAL( pszRefSystem, rstPLANE ) )
{
oSRS.SetLocalCS( "Plane" );
int nUnit = GetUnitIndex( pszRefUnits );
if( nUnit > -1 )
{
int nDeft = aoLinearUnitsConv[nUnit].nDefaultG;
oSRS.SetLinearUnits( aoLinearUnitsConv[nDeft].pszName,
aoLinearUnitsConv[nDeft].dfConv );
}
oSRS.exportToWkt( ppszProjString );
return CE_None;
}
// ---------------------------------------------------------
// Latlong
// ---------------------------------------------------------
if( EQUAL( pszRefSystem, rstLATLONG ) ||
EQUAL( pszRefSystem, rstLATLONG2 ) )
{
oSRS.SetWellKnownGeogCS( "WGS84" );
oSRS.exportToWkt( ppszProjString );
return CE_None;
}
// ---------------------------------------------------------
// Prepare for scanning in lower case
// ---------------------------------------------------------
char *pszRefSystemLower;
pszRefSystemLower = CPLStrdup( pszRefSystem );
CPLStrlwr( pszRefSystemLower );
// ---------------------------------------------------------
// UTM naming convention( ex.: utm-30n )
// ---------------------------------------------------------
if( EQUALN( pszRefSystem, rstUTM, 3 ) )
{
int nZone;
char cNorth;
sscanf( pszRefSystemLower, rstUTM, &nZone, &cNorth );
oSRS.SetWellKnownGeogCS( "WGS84" );
oSRS.SetUTM( nZone,( cNorth == 'n' ) );
oSRS.exportToWkt( ppszProjString );
CPLFree( pszRefSystemLower );
return CE_None;
}
// ---------------------------------------------------------
// State Plane naming convention( ex.: spc83ma1 )
// ---------------------------------------------------------
if( EQUALN( pszRefSystem, rstSPC, 3 ) )
{
int nNAD;
int nZone;
char szState[3];
sscanf( pszRefSystemLower, rstSPC, &nNAD, szState, &nZone );
int nSPCode = GetStateCode( szState );
if( nSPCode != -1 )
{
nZone = ( nZone == 1 ? nSPCode : nSPCode + nZone - 1 );
if( oSRS.SetStatePlane( nZone, ( nNAD == 83 ) ) != OGRERR_FAILURE )
{
oSRS.exportToWkt( ppszProjString );
CPLFree( pszRefSystemLower );
return CE_None;
}
// ----------------------------------------------------------
// If SetStatePlane fails, set GeoCS as NAD Datum and let it
// try to read the projection info from georeference file( * )
// ----------------------------------------------------------
oSRS.SetWellKnownGeogCS( CPLSPrintf( "NAD%d", nNAD ) );
}
}
CPLFree( pszRefSystemLower );
pszRefSystemLower = NULL;
// ------------------------------------------------------------------
// Search for georeference file <RefSystem>.ref
// ------------------------------------------------------------------
const char *pszFName = CPLSPrintf( "%s%c%s.ref",
CPLGetDirname( pszFilename ), PATHDELIM, pszRefSystem );
if( ! FileExists( pszFName ) )
{
// ------------------------------------------------------------------
// Look at $IDRISIDIR\Georef\<RefSystem>.ref
// ------------------------------------------------------------------
const char *pszIdrisiDir = CPLGetConfigOption( "IDRISIDIR", NULL );
if( ( pszIdrisiDir ) != NULL )
{
pszFName = CPLSPrintf( "%s%cgeoref%c%s.ref",
pszIdrisiDir, PATHDELIM, PATHDELIM, pszRefSystem );
}
}
// ------------------------------------------------------------------
// Cannot find georeference file
// ------------------------------------------------------------------
if( ! FileExists( pszFName ) )
{
CPLDebug( "RST", "Cannot find Idrisi georeference file %s",
pszRefSystem );
if( oSRS.IsGeographic() == FALSE ) /* see State Plane remarks( * ) */
{
oSRS.SetLocalCS( "Unknown" );
int nUnit = GetUnitIndex( pszRefUnits );
if( nUnit > -1 )
{
int nDeft = aoLinearUnitsConv[nUnit].nDefaultG;
oSRS.SetLinearUnits( aoLinearUnitsConv[nDeft].pszName,
aoLinearUnitsConv[nDeft].dfConv );
}
}
oSRS.exportToWkt( ppszProjString );
return CE_Failure;
}
// ------------------------------------------------------------------
// Read values from georeference file
// ------------------------------------------------------------------
char **papszRef = CSLLoad( pszFName );
CSLSetNameValueSeparator( papszRef, ":" );
char *pszGeorefName;
const char* pszREF_SYSTEM = CSLFetchNameValue( papszRef, refREF_SYSTEM );
if( pszREF_SYSTEM != NULL && EQUAL( pszREF_SYSTEM, "" ) == FALSE )
{
pszGeorefName = CPLStrdup( pszREF_SYSTEM );
}
else
{
pszGeorefName = CPLStrdup( CSLFetchNameValue( papszRef, refREF_SYSTEM2 ) );
}
char *pszProjName = CPLStrdup( CSLFetchNameValue( papszRef, refPROJECTION ) );
char *pszDatum = CPLStrdup( CSLFetchNameValue( papszRef, refDATUM ) );
char *pszEllipsoid = CPLStrdup( CSLFetchNameValue( papszRef, refELLIPSOID ) );
double dfCenterLat = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_LAT ) );
double dfCenterLong = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_LONG ) );
double dfSemiMajor = CPLAtof_nz( CSLFetchNameValue( papszRef, refMAJOR_SAX ) );
double dfSemiMinor = CPLAtof_nz( CSLFetchNameValue( papszRef, refMINOR_SAX ) );
double dfFalseEasting = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_X ) );
double dfFalseNorthing = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_Y ) );
double dfStdP1 = CPLAtof_nz( CSLFetchNameValue( papszRef, refSTANDL_1 ) );
double dfStdP2 = CPLAtof_nz( CSLFetchNameValue( papszRef, refSTANDL_2 ) );
double dfScale;
double adfToWGS84[3] = { 0.0, 0.0, 0.0 };
const char* pszToWGS84 = CSLFetchNameValue( papszRef, refDELTA_WGS84 );
if (pszToWGS84)
CPLsscanf( pszToWGS84, "%lf %lf %lf",
&adfToWGS84[0], &adfToWGS84[1], &adfToWGS84[2] );
const char* pszSCALE_FAC = CSLFetchNameValue( papszRef, refSCALE_FAC );
if( pszSCALE_FAC == NULL || EQUAL( pszSCALE_FAC, "na" ) )
dfScale = 1.0;
else
dfScale = CPLAtof_nz( pszSCALE_FAC );
CSLDestroy( papszRef );
// ----------------------------------------------------------------------
// Set the Geographic Coordinate System
// ----------------------------------------------------------------------
if( oSRS.IsGeographic() == FALSE ) /* see State Plane remarks(*) */
{
int nEPSG = 0;
// ----------------------------------------------------------------------
// Is it a WGS84 equivalent?
// ----------------------------------------------------------------------
if( ( EQUALN( pszEllipsoid, "WGS", 3 ) ) &&( strstr( pszEllipsoid, "84" ) ) &&
( EQUALN( pszDatum, "WGS", 3 ) ) &&( strstr( pszDatum, "84" ) ) &&
( adfToWGS84[0] == 0.0 ) &&( adfToWGS84[1] == 0.0 ) &&( adfToWGS84[2] == 0.0 ) )
{
nEPSG = 4326;
}
// ----------------------------------------------------------------------
// Match GCS's DATUM_NAME by using 'ApproxString' over Datum
// ----------------------------------------------------------------------
if( nEPSG == 0 )
{
nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ),
"DATUM_NAME", pszDatum, CC_ApproxString, "COORD_REF_SYS_CODE" ) );
}
// ----------------------------------------------------------------------
// Match GCS's COORD_REF_SYS_NAME by using 'ApproxString' over Datum
// ----------------------------------------------------------------------
if( nEPSG == 0 )
{
nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ),
"COORD_REF_SYS_NAME", pszDatum, CC_ApproxString, "COORD_REF_SYS_CODE" ) );
}
if( nEPSG != 0 )
{
oSRS.importFromEPSG( nEPSG );
}
else
{
// --------------------------------------------------
// Create GeogCS based on the georeference file info
// --------------------------------------------------
oSRS.SetGeogCS( pszRefSystem,
pszDatum,
pszEllipsoid,
dfSemiMajor,
(dfSemiMinor == dfSemiMajor) ? 0.0 : ( -1.0 /( dfSemiMinor / dfSemiMajor - 1.0 ) ) );
}
// ----------------------------------------------------------------------
// Note: That will override EPSG info:
// ----------------------------------------------------------------------
oSRS.SetTOWGS84( adfToWGS84[0], adfToWGS84[1], adfToWGS84[2] );
}
// ----------------------------------------------------------------------
// If the georeference file tells that it is a non project system:
// ----------------------------------------------------------------------
if( EQUAL( pszProjName, "none" ) )
{
oSRS.exportToWkt( ppszProjString );
CPLFree( pszGeorefName );
CPLFree( pszProjName );
CPLFree( pszDatum );
CPLFree( pszEllipsoid );
return CE_None;
}
// ----------------------------------------------------------------------
// Create Projection information based on georeference file info
// ----------------------------------------------------------------------
// Idrisi user's Manual, Supported Projection:
//
// Mercator
// Transverse Mercator
// Gauss-Kruger
// Lambert Conformal Conic
// Plate Carree
// Hammer Aitoff
// Lambert North Polar Azimuthal Equal Area
// Lambert South Polar Azimuthal Equal Area
// Lambert Transverse Azimuthal Equal Area
// Lambert Oblique Polar Azimuthal Equal Area
// North Polar Stereographic
// South Polar Stereographic
// Transverse Stereographic
// Oblique Stereographic
// Albers Equal Area Conic
// Sinusoidal
//
if( EQUAL( pszProjName, "Mercator" ) )
{
oSRS.SetMercator( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
}
else if EQUAL( pszProjName, "Transverse Mercator" )
{
oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
}
else if EQUALN( pszProjName, "Gauss-Kruger", 9 )
{
oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
}
else if( EQUAL( pszProjName, "Lambert Conformal Conic" ) )
{
oSRS.SetLCC( dfStdP1, dfStdP2, dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
}
else if( EQUALN( pszProjName, "Plate Carr" "\xE9" "e", 10 ) ) /* 'eacute' in ISO-8859-1 */
{
oSRS.SetEquirectangular( dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
}
else if( EQUAL( pszProjName, "Hammer Aitoff" ) )
{
oSRS.SetProjection( pszProjName );
oSRS.SetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
oSRS.SetProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
oSRS.SetProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
oSRS.SetProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
}
else if( EQUALN( pszProjName, "Lambert North Polar Azimuthal Equal Area", 15 ) ||
EQUALN( pszProjName, "Lambert South Polar Azimuthal Equal Area", 15 ) ||
EQUALN( pszProjName, "Lambert Transverse Azimuthal Equal Area", 15 ) ||
EQUALN( pszProjName, "Lambert Oblique Polar Azimuthal Equal Area", 15 ) )
{
oSRS.SetLAEA( dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
}
else if( EQUALN( pszProjName, "North Polar Stereographic", 15 ) ||
EQUALN( pszProjName, "South Polar Stereographic", 15 ) )
{
oSRS.SetPS( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
}
else if( EQUALN( pszProjName, "Transverse Stereographic", 15 ) )
{
oSRS.SetStereographic( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
}
else if( EQUALN( pszProjName, "Oblique Stereographic", 15 ) )
{
oSRS.SetOS( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
}
else if( EQUAL( pszProjName, "Alber's Equal Area Conic" ) ||
EQUAL( pszProjName, "Albers Equal Area Conic" ) )
{
oSRS.SetACEA( dfStdP1, dfStdP2, dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
}
else if( EQUAL( pszProjName, "Sinusoidal" ) )
{
oSRS.SetSinusoidal( dfCenterLong, dfFalseEasting, dfFalseNorthing );
}
else
{
CPLError( CE_Warning, CPLE_NotSupported,
"Projection not listed on Idrisi User's Manual( v.15.0/2005 ).\n\t"
"[\"%s\" in georeference file \"%s\"]",
pszProjName, pszFName );
oSRS.Clear();
oSRS.exportToWkt( ppszProjString );
CPLFree( pszGeorefName );
CPLFree( pszProjName );
CPLFree( pszDatum );
CPLFree( pszEllipsoid );
return CE_Warning;
}
// ----------------------------------------------------------------------
// Set the Linear Units
// ----------------------------------------------------------------------
int nUnit = GetUnitIndex( pszRefUnits );
if( nUnit > -1 )
{
int nDeft = aoLinearUnitsConv[nUnit].nDefaultG;
oSRS.SetLinearUnits( aoLinearUnitsConv[nDeft].pszName,
aoLinearUnitsConv[nDeft].dfConv );
}
else
{
oSRS.SetLinearUnits( "unknown", 1.0 );
}
// ----------------------------------------------------------------------
// Name ProjCS with the name on the georeference file
// ----------------------------------------------------------------------
oSRS.SetProjCS( pszGeorefName );
oSRS.exportToWkt( ppszProjString );
CPLFree( pszGeorefName );
CPLFree( pszProjName );
CPLFree( pszDatum );
CPLFree( pszEllipsoid );
return CE_None;
}
/************************************************************************/
/* Wkt2GeoReference() */
/************************************************************************/
/***
* Converts OpenGIS WKT to Idrisi geographic reference information.
*
* That function will fill up the two parameters RefSystem and RefUnit
* that goes into the Idrisi metadata. But it could also create
* a companying georeference file to the output if necessary.
*
* First it will try to identify the ProjString as Local, WGS84 or
* one of the Idrisi name convention reference systems
* otherwise, if the projection system is supported by Idrisi,
* it will create a companying georeference files.
***/
CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
char **pszRefSystem,
char **pszRefUnit )
{
// -----------------------------------------------------
// Plane with default "Meters"
// -----------------------------------------------------
if EQUAL( pszProjString, "" )
{
*pszRefSystem = CPLStrdup( rstPLANE );
*pszRefUnit = CPLStrdup( rstMETER );
return CE_None;
}
OGRSpatialReference oSRS;
oSRS.importFromWkt( (char **) &pszProjString );
// -----------------------------------------------------
// Local => Plane + Linear Unit
// -----------------------------------------------------
if( oSRS.IsLocal() )
{
*pszRefSystem = CPLStrdup( rstPLANE );
*pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ),
CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
return CE_None;
}
// -----------------------------------------------------
// Test to identify WGS84 => Latlong + Angular Unit
// -----------------------------------------------------
if( oSRS.IsGeographic() )
{
char *pszSpheroid = CPLStrdup( oSRS.GetAttrValue( "SPHEROID" ) );
char *pszAuthName = CPLStrdup( oSRS.GetAuthorityName( "GEOGCS" ) );
char *pszDatum = CPLStrdup( oSRS.GetAttrValue( "DATUM" ) );
int nGCSCode = -1;
if EQUAL( pszAuthName, "EPSG" )
{
nGCSCode = atoi( oSRS.GetAuthorityCode( "GEOGCS" ) );
}
if( ( nGCSCode == 4326 ) ||(
( EQUALN( pszSpheroid, "WGS", 3 ) ) &&( strstr( pszSpheroid, "84" ) ) &&
( EQUALN( pszDatum, "WGS", 3 ) ) &&( strstr( pszDatum, "84" ) ) ) )
{
*pszRefSystem = CPLStrdup( rstLATLONG );
*pszRefUnit = CPLStrdup( rstDEGREE );
CPLFree( pszSpheroid );
CPLFree( pszAuthName );
CPLFree( pszDatum );
return CE_None;
}
CPLFree( pszSpheroid );
CPLFree( pszAuthName );
CPLFree( pszDatum );
}
// -----------------------------------------------------
// Prepare to match some projections
// -----------------------------------------------------
const char *pszProjName = oSRS.GetAttrValue( "PROJECTION" );
if( pszProjName == NULL )
{
pszProjName = "";
}
// -----------------------------------------------------
// Check for UTM zones
// -----------------------------------------------------
if( EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR ) )
{
int nZone = oSRS.GetUTMZone();
if( ( nZone != 0 ) && ( EQUAL( oSRS.GetAttrValue( "DATUM" ), SRS_DN_WGS84 ) ) )
{
double dfNorth = oSRS.GetProjParm( SRS_PP_FALSE_NORTHING );
*pszRefSystem = CPLStrdup( CPLSPrintf( rstUTM, nZone,( dfNorth == 0.0 ? 'n' : 's' ) ) );
*pszRefUnit = CPLStrdup( rstMETER );
return CE_None;
}
}
// -----------------------------------------------------
// Check for State Plane
// -----------------------------------------------------
#ifndef GDAL_RST_PLUGIN
if( EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP ) ||
EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR ) )
{
const char *pszPCSCode;
const char *pszID = CPLStrdup( oSRS.GetAuthorityCode( "PROJCS" ) );
if( strlen( pszID ) > 0 )
{
pszPCSCode = CPLStrdup( CSVGetField( CSVFilename( "stateplane.csv" ),
"EPSG_PCS_CODE", pszID, CC_Integer, "ID" ) );
if( strlen( pszPCSCode ) > 0 )
{
int nNADYear = 83;
int nZone = pszPCSCode[strlen( pszPCSCode ) - 1] - '0';
int nSPCode = atoi_nz( pszPCSCode );
if( nZone == 0 )
nZone = 1;
else
nSPCode = nSPCode - nZone + 1;
if( nSPCode > 10000 )
{
nNADYear = 27;
nSPCode -= 10000;
}
char *pszState = CPLStrdup( GetStateName( nSPCode ) );
if( ! EQUAL( pszState, "" ) )
{
*pszRefSystem = CPLStrdup( CPLSPrintf( rstSPC, nNADYear, pszState, nZone ) );
*pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ),
CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
return CE_None;
}
}
}//
//if EPSG code is missing, go to following steps to work with origin
double dfLon = 0.0;
double dfLat = 0.0;
const char *pszNAD83 = "83";
const char *pszNAD27 = "27";
int isOldNAD = FALSE;
const char *pszDatumValue = oSRS.GetAttrValue("DATUM",0);
if( (strstr(pszDatumValue, pszNAD83) == NULL) && (strstr(pszDatumValue, pszNAD27) != NULL ))
//strcpy(pszNAD, "27");
isOldNAD = TRUE;
if ( (oSRS.FindProjParm("central_meridian",NULL) != -1) && (oSRS.FindProjParm("central_meridian",NULL) != -1) )
{
dfLon = oSRS.GetProjParm("central_meridian");
dfLat = oSRS.GetProjParm("latitude_of_origin");
dfLon = (int)(fabs(dfLon) * 100 + 0.5) / 100.0;
dfLat = (int)(fabs(dfLat) * 100 + 0.5) / 100.0;
*pszRefSystem = CPLStrdup(GetSpcs(dfLon, dfLat));
}
if(*pszRefSystem != NULL)
{
//Convert 83 TO 27
if(isOldNAD)
{
char pszOutRefSystem[9];
NAD83to27(pszOutRefSystem, *pszRefSystem);
*pszRefSystem = CPLStrdup(pszOutRefSystem);
}
*pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ), CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
return CE_None;
}
}
#endif // GDAL_RST_PLUGIN
const char *pszProjectionOut = NULL;
if( oSRS.IsProjected() )
{
// ---------------------------------------------------------
// Check for supported projections
// ---------------------------------------------------------
if EQUAL( pszProjName, SRS_PT_MERCATOR_1SP )
{
pszProjectionOut = "Mercator" ;
}
if EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR )
{
pszProjectionOut = "Transverse Mercator" ;
}
else if EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP )
{
pszProjectionOut = "Lambert Conformal Conic" ;
}
else if EQUAL( pszProjName, SRS_PT_EQUIRECTANGULAR )
{
pszProjectionOut = "Plate Carr" "\xE9" "e" ; /* 'eacute' in ISO-8859-1 */
}
else if EQUAL( pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA )
{
double dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
if( dfCenterLat == 0.0 )
pszProjectionOut = "Lambert Transverse Azimuthal Equal Area" ;
else if( fabs( dfCenterLat ) == 90.0 )
pszProjectionOut = "Lambert Oblique Polar Azimuthal Equal Area" ;
else if( dfCenterLat > 0.0 )
pszProjectionOut = "Lambert North Oblique Azimuthal Equal Area" ;
else
pszProjectionOut = "Lambert South Oblique Azimuthal Equal Area" ;
}
else if EQUAL( pszProjName, SRS_PT_POLAR_STEREOGRAPHIC )
{
if( oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL ) > 0 )
pszProjectionOut = "North Polar Stereographic" ;
else
pszProjectionOut = "South Polar Stereographic" ;
}
else if EQUAL( pszProjName, SRS_PT_STEREOGRAPHIC )
{
pszProjectionOut = "Transverse Stereographic" ;
}
else if EQUAL( pszProjName, SRS_PT_OBLIQUE_STEREOGRAPHIC )
{
pszProjectionOut = "Oblique Stereographic" ;
}
else if EQUAL( pszProjName, SRS_PT_SINUSOIDAL )
{
pszProjectionOut = "Sinusoidal" ;
}
else if EQUAL( pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA )
{
pszProjectionOut = "Alber's Equal Area Conic" ;
}
// ---------------------------------------------------------
// Failure, Projection system not suppotted
// ---------------------------------------------------------
if( pszProjectionOut == NULL )
{
CPLDebug( "RST",
"Not supported by RST driver: PROJECTION[\"%s\"]",
pszProjName );
*pszRefSystem = CPLStrdup( rstPLANE );
*pszRefUnit = CPLStrdup( rstMETER );
return CE_Failure;
}
}
else
{
pszProjectionOut = "none" ;
}
// ---------------------------------------------------------
// Prepare to write ref file
// ---------------------------------------------------------
char *pszGeorefName = CPLStrdup( "Unknown" );
char *pszDatum = CPLStrdup( oSRS.GetAttrValue( "DATUM" ) );
char *pszEllipsoid = CPLStrdup( oSRS.GetAttrValue( "SPHEROID" ) );
double dfSemiMajor = oSRS.GetSemiMajor();
double dfSemiMinor = oSRS.GetSemiMinor();
double adfToWGS84[3];
oSRS.GetTOWGS84( adfToWGS84, 3 );
double dfCenterLat = 0.0;
double dfCenterLong = 0.0;
double dfFalseNorthing = 0.0;
double dfFalseEasting = 0.0;
double dfScale = 1.0;
int nParameters = 0;
double dfStdP1 = 0.0;
double dfStdP2 = 0.0;
char *pszAngularUnit = CPLStrdup( oSRS.GetAttrValue( "GEOGCS|UNIT" ) );
char *pszLinearUnit;
if( oSRS.IsProjected() )
{
CPLFree( pszGeorefName );
pszGeorefName = CPLStrdup( oSRS.GetAttrValue( "PROJCS" ) );
dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
dfCenterLong = oSRS.GetProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL );
dfFalseNorthing = oSRS.GetProjParm( SRS_PP_FALSE_NORTHING, 0.0, NULL );
dfFalseEasting = oSRS.GetProjParm( SRS_PP_FALSE_EASTING, 0.0, NULL );
dfScale = oSRS.GetProjParm( SRS_PP_SCALE_FACTOR, 0.0, NULL );
dfStdP1 = oSRS.GetProjParm( SRS_PP_STANDARD_PARALLEL_1, -0.1, NULL );
dfStdP2 = oSRS.GetProjParm( SRS_PP_STANDARD_PARALLEL_2, -0.1, NULL );
if( dfStdP1 != -0.1 )
{
nParameters = 1;
if( dfStdP2 != -0.1 )
nParameters = 2;
}
pszLinearUnit = GetUnitDefault( oSRS.GetAttrValue( "PROJCS|UNIT" ),
CPLSPrintf( "%f", oSRS.GetLinearUnits() ) ) ;
}
else
{
pszLinearUnit = GetUnitDefault( pszAngularUnit );
}
// ---------------------------------------------------------
// Create a companion georeference file for this dataset
// ---------------------------------------------------------
char **papszRef = NULL;
papszRef = CSLAddNameValue( papszRef, refREF_SYSTEM, pszGeorefName );
papszRef = CSLAddNameValue( papszRef, refPROJECTION, pszProjectionOut );
papszRef = CSLAddNameValue( papszRef, refDATUM, pszDatum );
papszRef = CSLAddNameValue( papszRef, refDELTA_WGS84, CPLSPrintf( "%.3g %.3g %.3g",
adfToWGS84[0], adfToWGS84[1], adfToWGS84[2] ) );
papszRef = CSLAddNameValue( papszRef, refELLIPSOID, pszEllipsoid );
papszRef = CSLAddNameValue( papszRef, refMAJOR_SAX, CPLSPrintf( "%.3f", dfSemiMajor ) );
papszRef = CSLAddNameValue( papszRef, refMINOR_SAX, CPLSPrintf( "%.3f", dfSemiMinor ) );
papszRef = CSLAddNameValue( papszRef, refORIGIN_LONG, CPLSPrintf( "%.9g", dfCenterLong ) );
papszRef = CSLAddNameValue( papszRef, refORIGIN_LAT, CPLSPrintf( "%.9g", dfCenterLat ) );
papszRef = CSLAddNameValue( papszRef, refORIGIN_X, CPLSPrintf( "%.9g", dfFalseEasting ) );
papszRef = CSLAddNameValue( papszRef, refORIGIN_Y, CPLSPrintf( "%.9g", dfFalseNorthing ) );
papszRef = CSLAddNameValue( papszRef, refSCALE_FAC, CPLSPrintf( "%.9g", dfScale ) );
papszRef = CSLAddNameValue( papszRef, refUNITS, pszLinearUnit );
papszRef = CSLAddNameValue( papszRef, refPARAMETERS, CPLSPrintf( "%1d", nParameters ) );
if( nParameters > 0 )
papszRef = CSLAddNameValue( papszRef, refSTANDL_1, CPLSPrintf( "%.9g", dfStdP1 ) );
if( nParameters > 1 )
papszRef = CSLAddNameValue( papszRef, refSTANDL_2, CPLSPrintf( "%.9g", dfStdP2 ) );
CSLSetNameValueSeparator( papszRef, ": " );
SaveAsCRLF( papszRef, CPLResetExtension( pszFilename, extREF ) );
CSLDestroy( papszRef );
*pszRefSystem = CPLStrdup( CPLGetBasename( pszFilename ) );
*pszRefUnit = CPLStrdup( pszLinearUnit );
CPLFree( pszGeorefName );
CPLFree( pszDatum );
CPLFree( pszEllipsoid );
CPLFree( pszLinearUnit );
CPLFree( pszAngularUnit );
return CE_None;
}
/************************************************************************/
/* FileExists() */
/************************************************************************/
bool FileExists( const char *pszPath )
{
VSIStatBufL sStat;
return (bool) ( VSIStatL( pszPath, &sStat ) == 0 );
}
/************************************************************************/
/* GetStateCode() */
/************************************************************************/
int GetStateCode( const char *pszState )
{
unsigned int i;
for( i = 0; i < US_STATE_COUNT; i++ )
{
if EQUAL( pszState, aoUSStateTable[i].pszName )
{
return aoUSStateTable[i].nCode;
}
}
return -1;
}
/************************************************************************/
/* GetStateName() */
/************************************************************************/
const char *GetStateName( int nCode )
{
unsigned int i;
for( i = 0; i < US_STATE_COUNT; i++ )
{
if( nCode == aoUSStateTable[i].nCode )
{
return aoUSStateTable[i].pszName;
}
}
return NULL;
}
/************************************************************************/
/* GetSpcs() */
/************************************************************************/
char *GetSpcs(double dfLon, double dfLat)
{
int i;
for( i=0; i<ORIGIN_COUNT; i++)
{
if(( dfLon == SPCS83Origin[i].longitude ) && ( dfLat == SPCS83Origin[i].latitude ))
{
return (char *)SPCS83Origin[i].spcs;
}
}
return NULL;
}
/************************************************************************/
/* NAD83to27() */
/************************************************************************/
void NAD83to27( char *pszOutRef, char *pszInRef)
{
char *pOutput, *pInput;
pOutput = pszOutRef;
pInput = pszInRef;
strncpy(pOutput, pInput, 3);
pOutput = pOutput +3;
pInput = pInput +3;
strncpy(pOutput, "27", 2);
pOutput = pOutput +2;
pInput = pInput +2;
strcpy(pOutput, pInput);
}
/************************************************************************/
/* GetUnitIndex() */
/************************************************************************/
int GetUnitIndex( const char *pszUnitName )
{
int i;
for( i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
{
if EQUAL( pszUnitName, aoLinearUnitsConv[i].pszName )
{
return i;
}
}
return -1;
}
/************************************************************************/
/* GetToMeterIndex() */
/************************************************************************/
int GetToMeterIndex( const char *pszToMeter )
{
double dfToMeter = CPLAtof_nz(pszToMeter);
if( dfToMeter != 0.0 )
{
int i;
for( i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
{
if ( ABS( aoLinearUnitsConv[i].dfConv - dfToMeter ) < 0.00001 )
{
return i;
}
}
}
return -1;
}
/************************************************************************/
/* GetUnitDefault() */
/************************************************************************/
char *GetUnitDefault( const char *pszUnitName, const char *pszToMeter )
{
int nIndex = GetUnitIndex( pszUnitName );
if( nIndex == -1 && pszToMeter != NULL )
{
nIndex = GetToMeterIndex( pszToMeter );
}
if( nIndex == -1 )
{
return CPLStrdup( "Unknown" );
}
return CPLStrdup( aoLinearUnitsConv[aoLinearUnitsConv[nIndex].nDefaultI].pszName );
}
/************************************************************************/
/* CSLSaveCRLF() */
/************************************************************************/
/***
* Write a stringlist to a CR + LF terminated text file.
*
* Returns the number of lines written, or 0 if the file could not
* be written.
*/
int SaveAsCRLF(char **papszStrList, const char *pszFname)
{
VSILFILE *fp;
int nLines = 0;
if (papszStrList)
{
if ((fp = VSIFOpenL(pszFname, "wt")) != NULL)
{
while(*papszStrList != NULL)
{
if( VSIFPrintfL( fp, "%s\r\n", *papszStrList ) < 1 )
{
CPLError( CE_Failure, CPLE_FileIO,
"CSLSaveCRLF(\"%s\") failed: unable to write to output file.",
pszFname );
break;
}
nLines++;
papszStrList++;
}
VSIFCloseL(fp);
}
else
{
CPLError( CE_Failure, CPLE_OpenFailed,
"CSLSaveCRLF(\"%s\") failed: unable to open output file.",
pszFname );
}
}
return nLines;
}
/************************************************************************/
/* GDALRegister_IDRISI() */
/************************************************************************/
void GDALRegister_IDRISI()
{
GDALDriver *poDriver;
if( GDALGetDriverByName( "RST" ) == NULL )
{
poDriver = new GDALDriver();
poDriver->SetDescription( "RST" );
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, rstVERSION );
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_Idrisi.html" );
poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, extRST );
poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 Float32" );
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
poDriver->pfnOpen = IdrisiDataset::Open;
poDriver->pfnCreate = IdrisiDataset::Create;
poDriver->pfnCreateCopy = IdrisiDataset::CreateCopy;
GetGDALDriverManager()->RegisterDriver( poDriver );
}
}