1 : /*****************************************************************************
2 : * $Id: IdrisiDataset.cpp 18083 2009-11-23 15:15:44Z ilucena $
3 : *
4 : * Project: Idrisi Raster Image File Driver
5 : * Purpose: Read/write Idrisi Raster Image Format RST
6 : * Author: Ivan Lucena, ivan.lucena@pmldnet.com
7 : *
8 : ******************************************************************************
9 : * Copyright( c ) 2006, Ivan Lucena
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files( the "Software" ),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdal_priv.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "cpl_csv.h"
34 : #include "ogr_spatialref.h"
35 : #include "gdal_pam.h"
36 : #include "gdal_alg.h"
37 : #include "gdal_rat.h"
38 :
39 : CPL_CVSID( "$Id: IdrisiDataset.cpp 18083 2009-11-23 15:15:44Z ilucena $" );
40 :
41 : CPL_C_START
42 : void GDALRegister_IDRISI( void);
43 : CPL_C_END
44 :
45 : #ifdef WIN32
46 : #define PATHDELIM '\\'
47 : #else
48 : #define PATHDELIM '/'
49 : #endif
50 :
51 : //----- Safe numeric conversion, NULL as zero
52 : #define atoi_nz(s) (s == NULL ? (int) 0 : atoi(s))
53 : #define atof_nz(s) (s == NULL ? (double) 0.0 : atof(s))
54 :
55 : //----- file extensions:
56 : #define extRST "rst"
57 : #define extRDC "rdc"
58 : #define extSMP "smp"
59 : #define extREF "ref"
60 : #define extRSTu "RST"
61 : #define extRDCu "RDC"
62 : #define extSMPu "SMP"
63 : #define extREFu "REF"
64 :
65 : //----- field names on rdc file:
66 : #define rdcFILE_FORMAT "file format "
67 : #define rdcFILE_TITLE "file title "
68 : #define rdcDATA_TYPE "data type "
69 : #define rdcFILE_TYPE "file type "
70 : #define rdcCOLUMNS "columns "
71 : #define rdcROWS "rows "
72 : #define rdcREF_SYSTEM "ref. system "
73 : #define rdcREF_UNITS "ref. units "
74 : #define rdcUNIT_DIST "unit dist. "
75 : #define rdcMIN_X "min. X "
76 : #define rdcMAX_X "max. X "
77 : #define rdcMIN_Y "min. Y "
78 : #define rdcMAX_Y "max. Y "
79 : #define rdcPOSN_ERROR "pos'n error "
80 : #define rdcRESOLUTION "resolution "
81 : #define rdcMIN_VALUE "min. value "
82 : #define rdcMAX_VALUE "max. value "
83 : #define rdcDISPLAY_MIN "display min "
84 : #define rdcDISPLAY_MAX "display max "
85 : #define rdcVALUE_UNITS "value units "
86 : #define rdcVALUE_ERROR "value error "
87 : #define rdcFLAG_VALUE "flag value "
88 : #define rdcFLAG_DEFN "flag def'n "
89 : #define rdcFLAG_DEFN2 "flag def`n "
90 : #define rdcLEGEND_CATS "legend cats "
91 : #define rdcLINEAGES "lineage "
92 : #define rdcCOMMENTS "comment "
93 : #define rdcCODE_N "code %6d "
94 :
95 : //----- ".ref" file field names:
96 : #define refREF_SYSTEM "ref. system "
97 : #define refREF_SYSTEM2 "ref.system "
98 : #define refPROJECTION "projection "
99 : #define refDATUM "datum "
100 : #define refDELTA_WGS84 "delta WGS84 "
101 : #define refELLIPSOID "ellipsoid "
102 : #define refMAJOR_SAX "major s-ax "
103 : #define refMINOR_SAX "minor s-ax "
104 : #define refORIGIN_LONG "origin long "
105 : #define refORIGIN_LAT "origin lat "
106 : #define refORIGIN_X "origin X "
107 : #define refORIGIN_Y "origin Y "
108 : #define refSCALE_FAC "scale fac "
109 : #define refUNITS "units "
110 : #define refPARAMETERS "parameters "
111 : #define refSTANDL_1 "stand ln 1 "
112 : #define refSTANDL_2 "stand ln 2 "
113 :
114 : //----- standard values:
115 : #define rstVERSION "Idrisi Raster A.1"
116 : #define rstBYTE "byte"
117 : #define rstINTEGER "integer"
118 : #define rstREAL "real"
119 : #define rstRGB24 "rgb24"
120 : #define rstDEGREE "deg"
121 : #define rstMETER "m"
122 : #define rstLATLONG "latlong"
123 : #define rstLATLONG2 "lat/long"
124 : #define rstPLANE "plane"
125 : #define rstUTM "utm-%d%c"
126 : #define rstSPC "spc%2d%2s%d"
127 :
128 : //----- palette file( .smp ) header size:
129 : #define smpHEADERSIZE 18
130 :
131 : //----- check if file exists:
132 : bool FileExists( const char *pszPath );
133 :
134 : //----- Reference Table
135 : struct ReferenceTab {
136 : int nCode;
137 : const char *pszName;
138 : };
139 :
140 : //----- USA State's reference table to USGS PCS Code
141 : static const ReferenceTab aoUSStateTable[] = {
142 : {101, "al"},
143 : {201, "az"},
144 : {301, "ar"},
145 : {401, "ca"},
146 : {501, "co"},
147 : {600, "ct"},
148 : {700, "de"},
149 : {901, "fl"},
150 : {1001, "ga"},
151 : {1101, "id"},
152 : {1201, "il"},
153 : {1301, "in"},
154 : {1401, "ia"},
155 : {1501, "ks"},
156 : {1601, "ky"},
157 : {1701, "la"},
158 : {1801, "me"},
159 : {1900, "md"},
160 : {2001, "ma"},
161 : {2111, "mi"},
162 : {2201, "mn"},
163 : {2301, "ms"},
164 : {2401, "mo"},
165 : {2500, "mt"},
166 : {2600, "ne"},
167 : {2701, "nv"},
168 : {2800, "nh"},
169 : {2900, "nj"},
170 : {3001, "nm"},
171 : {3101, "ny"},
172 : {3200, "nc"},
173 : {3301, "nd"},
174 : {3401, "oh"},
175 : {3501, "ok"},
176 : {3601, "or"},
177 : {3701, "pa"},
178 : {3800, "ri"},
179 : {3900, "sc"},
180 : {4001, "sd"},
181 : {4100, "tn"},
182 : {4201, "tx"},
183 : {4301, "ut"},
184 : {4400, "vt"},
185 : {4501, "va"},
186 : {4601, "wa"},
187 : {4701, "wv"},
188 : {4801, "wv"},
189 : {4901, "wy"},
190 : {5001, "ak"},
191 : {5101, "hi"},
192 : {5200, "pr"}
193 : };
194 : #define US_STATE_COUNT ( sizeof( aoUSStateTable ) / sizeof( ReferenceTab ) )
195 :
196 : //----- Get the Code of a US State
197 : int GetStateCode ( const char *pszState );
198 :
199 : //----- Get the state name of a Code
200 : const char *GetStateName( int nCode );
201 :
202 : //----- Conversion Table definition
203 : struct ConvertionTab {
204 : const char *pszName;
205 : int nDefaultI;
206 : int nDefaultG;
207 : double dfConv;
208 : };
209 :
210 : //----- Linear Unit Conversion Table
211 : static const ConvertionTab aoLinearUnitsConv[] = {
212 : {"m", /* 0 */ 0, 1, 1.0},
213 : {SRS_UL_METER, /* 1 */ 0, 1, 1.0},
214 : {"meters", /* 2 */ 0, 1, 1.0},
215 : {"metre", /* 3 */ 0, 1, 1.0},
216 :
217 : {"ft", /* 4 */ 4, 5, 0.3048},
218 : {SRS_UL_FOOT, /* 5 */ 4, 5, 0.3048},
219 : {"feet", /* 6 */ 4, 5, 0.3048},
220 : {"foot_us", /* 7 */ 4, 5, 0.3048006},
221 : {"u.s. foot", /* 8 */ 4, 5, 0.3048006},
222 :
223 : {"mi", /* 9 */ 9, 10, 1612.9},
224 : {"mile", /* 10 */ 9, 10, 1612.9},
225 : {"miles", /* 11 */ 9, 10, 1612.9},
226 :
227 : {"km", /* 12 */ 12, 13, 1000.0},
228 : {"kilometers", /* 13 */ 12, 13, 1000.0},
229 : {"kilometer", /* 14 */ 12, 13, 1000.0},
230 : {"kilometre", /* 15 */ 12, 13, 1000.0},
231 :
232 : {"deg", /* 16 */ 16, 17, 0.0},
233 : {SRS_UA_DEGREE, /* 17 */ 16, 17, 0.0},
234 : {"degrees", /* 18 */ 16, 17, 0.0},
235 :
236 : {"rad", /* 19 */ 19, 20, 0.0},
237 : {SRS_UA_RADIAN, /* 20 */ 19, 20, 0.0},
238 : {"radians", /* 21 */ 19, 20, 0.0}
239 : };
240 : #define LINEAR_UNITS_COUNT (sizeof(aoLinearUnitsConv) / sizeof(ConvertionTab))
241 :
242 : //----- Get the index of a given linear unit
243 : int GetUnitIndex( const char *pszUnitName );
244 :
245 : //----- Get the defaut name
246 : char *GetUnitDefault( const char *pszUnitName, const char *pszToMeter = NULL );
247 :
248 : //----- Get the "to meter"
249 : int GetToMeterIndex( const char *pszToMeter );
250 :
251 : //----- CSLSaveCRLF
252 : int SaveAsCRLF(char **papszStrList, const char *pszFname);
253 :
254 : //----- Classes pre-definition:
255 : class IdrisiDataset;
256 : class IdrisiRasterBand;
257 :
258 : // ----------------------------------------------------------------------------
259 : // Idrisi GDALDataset
260 : // ----------------------------------------------------------------------------
261 :
262 : class IdrisiDataset : public GDALPamDataset
263 : {
264 : friend class IdrisiRasterBand;
265 :
266 : private:
267 : FILE *fp;
268 :
269 : char *pszFilename;
270 : char *pszDocFilename;
271 : char **papszRDC;
272 : double adfGeoTransform[6];
273 :
274 : char *pszProjection;
275 : char **papszCategories;
276 : char *pszUnitType;
277 :
278 : CPLErr GeoReference2Wkt( const char *pszRefSystem,
279 : const char *pszRefUnits,
280 : char **pszProjString );
281 :
282 : CPLErr Wkt2GeoReference( const char *pszProjString,
283 : char **pszRefSystem,
284 : char **pszRefUnit );
285 :
286 : protected:
287 : GDALColorTable *poColorTable;
288 :
289 : public:
290 : IdrisiDataset();
291 : ~IdrisiDataset();
292 :
293 : static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
294 : static GDALDataset *Create( const char *pszFilename,
295 : int nXSize,
296 : int nYSize,
297 : int nBands,
298 : GDALDataType eType,
299 : char **papszOptions );
300 : static GDALDataset *CreateCopy( const char *pszFilename,
301 : GDALDataset *poSrcDS,
302 : int bStrict,
303 : char **papszOptions,
304 : GDALProgressFunc pfnProgress,
305 : void * pProgressData );
306 : virtual char **GetFileList(void);
307 : virtual CPLErr GetGeoTransform( double *padfTransform );
308 : virtual CPLErr SetGeoTransform( double *padfTransform );
309 : virtual const char *GetProjectionRef( void );
310 : virtual CPLErr SetProjection( const char *pszProjString );
311 : };
312 :
313 : // ----------------------------------------------------------------------------
314 : // Idrisi GDALPamRasterBand
315 : // ----------------------------------------------------------------------------
316 :
317 : class IdrisiRasterBand : public GDALPamRasterBand
318 : {
319 : friend class IdrisiDataset;
320 :
321 : GDALRasterAttributeTable *poDefaultRAT;
322 :
323 : private:
324 : int nRecordSize;
325 : GByte *pabyScanLine;
326 :
327 : public:
328 : IdrisiRasterBand( IdrisiDataset *poDS,
329 : int nBand,
330 : GDALDataType eDataType );
331 : ~IdrisiRasterBand();
332 :
333 : virtual double GetNoDataValue( int *pbSuccess = NULL );
334 : virtual double GetMinimum( int *pbSuccess = NULL );
335 : virtual double GetMaximum( int *pbSuccess = NULL );
336 : virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
337 : virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage );
338 : virtual GDALColorTable *GetColorTable();
339 : virtual GDALColorInterp GetColorInterpretation();
340 : virtual char **GetCategoryNames();
341 : virtual const char *GetUnitType();
342 :
343 : virtual CPLErr SetCategoryNames( char **papszCategoryNames );
344 : virtual CPLErr SetNoDataValue( double dfNoDataValue );
345 : virtual CPLErr SetColorTable( GDALColorTable *poColorTable );
346 : virtual CPLErr SetUnitType( const char *pszUnitType );
347 : virtual CPLErr SetStatistics( double dfMin, double dfMax,
348 : double dfMean, double dfStdDev );
349 : virtual const GDALRasterAttributeTable *GetDefaultRAT();
350 : virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
351 :
352 : float dfMaximum;
353 : float dfMinimum;
354 : bool bFirstVal;
355 : };
356 :
357 : // ------------------------------------------------------------------------ //
358 : // Implementation of IdrisiDataset //
359 : // ------------------------------------------------------------------------ //
360 :
361 : /************************************************************************/
362 : /* IdrisiDataset() */
363 : /************************************************************************/
364 :
365 8 : IdrisiDataset::IdrisiDataset()
366 : {
367 8 : pszFilename = NULL;
368 8 : fp = NULL;
369 8 : papszRDC = NULL;
370 8 : pszDocFilename = NULL;
371 8 : pszProjection = NULL;
372 8 : poColorTable = new GDALColorTable();
373 8 : papszCategories = NULL;
374 8 : pszUnitType = NULL;
375 :
376 8 : adfGeoTransform[0] = 0.0;
377 8 : adfGeoTransform[1] = 1.0;
378 8 : adfGeoTransform[2] = 0.0;
379 8 : adfGeoTransform[3] = 0.0;
380 8 : adfGeoTransform[4] = 0.0;
381 8 : adfGeoTransform[5] = 1.0;
382 8 : }
383 :
384 : /************************************************************************/
385 : /* ~IdrisiDataset() */
386 : /************************************************************************/
387 :
388 16 : IdrisiDataset::~IdrisiDataset()
389 : {
390 8 : FlushCache();
391 :
392 8 : if( papszRDC != NULL )
393 : {
394 8 : if( eAccess == GA_Update )
395 : {
396 : int i;
397 :
398 6 : for( i = 0; i < nBands; i++ )
399 : {
400 4 : IdrisiRasterBand *poBand = (IdrisiRasterBand*) GetRasterBand( i + 1 );
401 4 : poBand->SetStatistics( poBand->dfMinimum, poBand->dfMaximum, 0.0, 0.0 );
402 : }
403 :
404 2 : CSLSetNameValueSeparator( papszRDC, ": " );
405 2 : SaveAsCRLF( papszRDC, pszDocFilename );
406 : }
407 8 : CSLDestroy( papszRDC );
408 : }
409 :
410 8 : if( poColorTable )
411 : {
412 8 : delete poColorTable;
413 : }
414 8 : CPLFree( pszFilename );
415 8 : CPLFree( pszDocFilename );
416 8 : CPLFree( pszProjection );
417 8 : CSLDestroy( papszCategories );
418 8 : CPLFree( pszUnitType );
419 :
420 8 : if( fp != NULL )
421 8 : VSIFCloseL( fp );
422 16 : }
423 :
424 : /************************************************************************/
425 : /* Open() */
426 : /************************************************************************/
427 :
428 8884 : GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
429 : {
430 8884 : if( ( poOpenInfo->fp == NULL ) ||
431 : ( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), extRST ) == FALSE ) )
432 8876 : return NULL;
433 :
434 : // --------------------------------------------------------------------
435 : // Check the documentation file .rdc
436 : // --------------------------------------------------------------------
437 :
438 8 : const char *pszLDocFilename = CPLResetExtension( poOpenInfo->pszFilename, extRDC );
439 :
440 8 : if( ! FileExists( pszLDocFilename ) )
441 : {
442 0 : pszLDocFilename = CPLResetExtension( poOpenInfo->pszFilename, extRDCu );
443 :
444 0 : if( ! FileExists( pszLDocFilename ) )
445 : {
446 0 : return NULL;
447 : }
448 : }
449 :
450 8 : char **papszLRDC = CSLLoad( pszLDocFilename );
451 :
452 8 : CSLSetNameValueSeparator( papszLRDC, ":" );
453 :
454 8 : const char *pszVersion = CSLFetchNameValue( papszLRDC, rdcFILE_FORMAT );
455 :
456 8 : if( pszVersion == NULL || !EQUAL( pszVersion, rstVERSION ) )
457 : {
458 0 : CSLDestroy( papszLRDC );
459 0 : return NULL;
460 : }
461 :
462 : // --------------------------------------------------------------------
463 : // Create a corresponding GDALDataset
464 : // --------------------------------------------------------------------
465 :
466 : IdrisiDataset *poDS;
467 :
468 8 : poDS = new IdrisiDataset();
469 8 : poDS->eAccess = poOpenInfo->eAccess;
470 8 : poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename );
471 :
472 8 : if( poOpenInfo->eAccess == GA_ReadOnly )
473 : {
474 6 : poDS->fp = VSIFOpenL( poDS->pszFilename, "rb" );
475 : }
476 : else
477 : {
478 2 : poDS->fp = VSIFOpenL( poDS->pszFilename, "r+b" );
479 : }
480 :
481 8 : if( poDS->fp == NULL )
482 : {
483 0 : CSLDestroy( papszLRDC );
484 0 : return NULL;
485 : }
486 :
487 8 : poDS->pszDocFilename = CPLStrdup( pszLDocFilename );
488 8 : poDS->papszRDC = CSLDuplicate( papszLRDC );
489 8 : CSLDestroy( papszLRDC );
490 :
491 : // --------------------------------------------------------------------
492 : // Load information from rdc
493 : // --------------------------------------------------------------------
494 :
495 8 : poDS->nRasterXSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcCOLUMNS ) );
496 8 : poDS->nRasterYSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcROWS ) );
497 :
498 : // --------------------------------------------------------------------
499 : // Create band information
500 : // --------------------------------------------------------------------
501 :
502 8 : const char *pszDataType = CSLFetchNameValue( poDS->papszRDC, rdcDATA_TYPE );
503 :
504 8 : if( EQUAL( pszDataType, rstBYTE ) )
505 : {
506 1 : poDS->nBands = 1;
507 1 : poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Byte ) );
508 : }
509 7 : else if( EQUAL( pszDataType, rstINTEGER ) )
510 : {
511 0 : poDS->nBands = 1;
512 0 : poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Int16 ) );
513 : }
514 7 : else if( EQUAL( pszDataType, rstREAL ) )
515 : {
516 4 : poDS->nBands = 1;
517 4 : poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Float32 ) );
518 : }
519 3 : else if( EQUAL( pszDataType, rstRGB24 ) )
520 : {
521 3 : poDS->nBands = 3;
522 3 : poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Byte ) );
523 6 : poDS->SetBand( 2, new IdrisiRasterBand( poDS, 2, GDT_Byte ) );
524 6 : poDS->SetBand( 3, new IdrisiRasterBand( poDS, 3, GDT_Byte ) );
525 : }
526 : else
527 : {
528 : CPLError(CE_Failure, CPLE_AppDefined,
529 0 : "Unknown data type : %s", pszDataType);
530 0 : delete poDS;
531 0 : return NULL;
532 : }
533 :
534 : int i;
535 22 : for(i=0;i<poDS->nBands;i++)
536 : {
537 14 : IdrisiRasterBand* band = (IdrisiRasterBand*) poDS->GetRasterBand(i+1);
538 14 : if (band->pabyScanLine == NULL)
539 : {
540 0 : delete poDS;
541 0 : return NULL;
542 : }
543 : }
544 :
545 : // --------------------------------------------------------------------
546 : // Load the transformation matrix
547 : // --------------------------------------------------------------------
548 :
549 8 : const char *pszMinX = CSLFetchNameValue( poDS->papszRDC, rdcMIN_X );
550 :
551 8 : if( strlen( pszMinX ) > 0 )
552 : {
553 : double dfMinX, dfMaxX, dfMinY, dfMaxY, dfUnit, dfXPixSz, dfYPixSz;
554 :
555 8 : dfMinX = atof_nz( CSLFetchNameValue( poDS->papszRDC, rdcMIN_X ) );
556 8 : dfMaxX = atof_nz( CSLFetchNameValue( poDS->papszRDC, rdcMAX_X ) );
557 8 : dfMinY = atof_nz( CSLFetchNameValue( poDS->papszRDC, rdcMIN_Y ) );
558 8 : dfMaxY = atof_nz( CSLFetchNameValue( poDS->papszRDC, rdcMAX_Y ) );
559 8 : dfUnit = atof_nz( CSLFetchNameValue( poDS->papszRDC, rdcUNIT_DIST ) );
560 :
561 8 : dfMinX = dfMinX * dfUnit;
562 8 : dfMaxX = dfMaxX * dfUnit;
563 8 : dfMinY = dfMinY * dfUnit;
564 8 : dfMaxY = dfMaxY * dfUnit;
565 :
566 8 : dfYPixSz = ( dfMinY - dfMaxY ) / poDS->nRasterYSize;
567 8 : dfXPixSz = ( dfMaxX - dfMinX ) / poDS->nRasterXSize;
568 :
569 8 : poDS->adfGeoTransform[0] = dfMinX;
570 8 : poDS->adfGeoTransform[1] = dfXPixSz;
571 8 : poDS->adfGeoTransform[2] = 0.0;
572 8 : poDS->adfGeoTransform[3] = dfMaxY;
573 8 : poDS->adfGeoTransform[4] = 0.0;
574 8 : poDS->adfGeoTransform[5] = dfYPixSz;
575 : }
576 :
577 : // --------------------------------------------------------------------
578 : // Set Color Table in the presence of a smp file
579 : // --------------------------------------------------------------------
580 :
581 8 : if( poDS->nBands != 3 )
582 : {
583 5 : const char *pszSMPFilename = CPLResetExtension( poDS->pszFilename, extSMP );
584 : FILE *fpSMP;
585 5 : if( ( fpSMP = VSIFOpenL( pszSMPFilename, "rb" ) ) != NULL )
586 : {
587 0 : double dfMaxValue = atof_nz( CSLFetchNameValue( poDS->papszRDC, rdcMAX_VALUE ) );
588 0 : VSIFSeekL( fpSMP, smpHEADERSIZE, SEEK_SET );
589 : GDALColorEntry oEntry;
590 : unsigned char aucRGB[3];
591 0 : int i = 0;
592 0 : while( ( VSIFReadL( &aucRGB, sizeof( aucRGB ), 1, fpSMP ) ) &&( i <= dfMaxValue ) )
593 : {
594 0 : oEntry.c1 = (short) aucRGB[0];
595 0 : oEntry.c2 = (short) aucRGB[1];
596 0 : oEntry.c3 = (short) aucRGB[2];
597 0 : oEntry.c4 = (short) 255;
598 0 : poDS->poColorTable->SetColorEntry( i, &oEntry );
599 0 : i++;
600 : }
601 0 : VSIFCloseL( fpSMP );
602 : }
603 : }
604 :
605 : // --------------------------------------------------------------------
606 : // Check for Unit Type
607 : // --------------------------------------------------------------------
608 :
609 8 : const char *pszValueUnit = CSLFetchNameValue( poDS->papszRDC, rdcVALUE_UNITS );
610 :
611 8 : if( pszValueUnit == NULL )
612 0 : poDS->pszUnitType = CPLStrdup( "unspecified" );
613 : else
614 : {
615 8 : if( EQUALN( pszValueUnit, "meter", 4 ) )
616 : {
617 0 : poDS->pszUnitType = CPLStrdup( "m" );
618 : }
619 8 : else if( EQUALN( pszValueUnit, "feet", 4 ) )
620 : {
621 0 : poDS->pszUnitType = CPLStrdup( "ft" );
622 : }
623 : else
624 8 : poDS->pszUnitType = CPLStrdup( pszValueUnit );
625 : }
626 :
627 : // --------------------------------------------------------------------
628 : // Check for category names.
629 : // --------------------------------------------------------------------
630 :
631 8 : int nCatCount = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcLEGEND_CATS ) );
632 :
633 8 : if( nCatCount > 0 )
634 : {
635 : // ----------------------------------------------------------------
636 : // Sequentialize categories names, from 0 to the last "code n"
637 : // ----------------------------------------------------------------
638 :
639 0 : int nCode = 0;
640 0 : int nCount = 0;
641 0 : int nLine = -1;
642 0 : for( int i = 0;( i < CSLCount( poDS->papszRDC ) ) &&( nLine == -1 ); i++ )
643 0 : if( EQUALN( poDS->papszRDC[i], rdcLEGEND_CATS, 11 ) )
644 0 : nLine = i;
645 0 : if( nLine > 0 )
646 : {
647 0 : sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );
648 0 : for( int i = 0;( i < 255 ) &&( nCount < nCatCount ); i++ )
649 : {
650 0 : if( i == nCode )
651 : {
652 : poDS->papszCategories =
653 : CSLAddString( poDS->papszCategories,
654 0 : CPLParseNameValue( poDS->papszRDC[nLine], NULL ) );
655 0 : nCount++;
656 0 : if( nCount < nCatCount )
657 0 : sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );
658 : }
659 : else
660 0 : poDS->papszCategories = CSLAddString( poDS->papszCategories, "" );
661 : }
662 : }
663 : }
664 :
665 : /* -------------------------------------------------------------------- */
666 : /* Automatic Generated Color Table */
667 : /* -------------------------------------------------------------------- */
668 :
669 8 : if( poDS->papszCategories != NULL &&
670 : ( poDS->poColorTable->GetColorEntryCount() == 0 ) )
671 : {
672 0 : int nEntryCount = CSLCount(poDS->papszCategories);
673 :
674 : GDALColorEntry sFromColor;
675 0 : sFromColor.c1 = (short) ( 255 );
676 0 : sFromColor.c2 = (short) ( 0 );
677 0 : sFromColor.c3 = (short) ( 0 );
678 0 : sFromColor.c4 = (short) ( 255 );
679 :
680 : GDALColorEntry sToColor;
681 0 : sToColor.c1 = (short) ( 0 );
682 0 : sToColor.c2 = (short) ( 0 );
683 0 : sToColor.c3 = (short) ( 255 );
684 0 : sToColor.c4 = (short) ( 255 );
685 :
686 : poDS->poColorTable->CreateColorRamp(
687 0 : 0, &sFromColor, ( nEntryCount - 1 ), &sToColor );
688 : }
689 :
690 : /* -------------------------------------------------------------------- */
691 : /* Initialize any PAM information. */
692 : /* -------------------------------------------------------------------- */
693 :
694 8 : poDS->SetDescription( poOpenInfo->pszFilename );
695 8 : poDS->TryLoadXML();
696 :
697 : /* -------------------------------------------------------------------- */
698 : /* Check for external overviews. */
699 : /* -------------------------------------------------------------------- */
700 :
701 8 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
702 :
703 8 : return( poDS );
704 : }
705 :
706 : /************************************************************************/
707 : /* Create() */
708 : /************************************************************************/
709 :
710 22 : GDALDataset *IdrisiDataset::Create( const char *pszFilename,
711 : int nXSize,
712 : int nYSize,
713 : int nBands,
714 : GDALDataType eType,
715 : char **papszOptions )
716 : {
717 : (void) papszOptions;
718 :
719 : // --------------------------------------------------------------------
720 : // Check input options
721 : // --------------------------------------------------------------------
722 :
723 22 : if( nBands != 1 )
724 : {
725 7 : if( !( nBands == 3 && eType == GDT_Byte ) )
726 : {
727 : CPLError( CE_Failure, CPLE_AppDefined,
728 : "Attempt to create IDRISI dataset with an illegal "
729 : "number of bands(%d) or data type(%s).\n",
730 4 : nBands, GDALGetDataTypeName( eType ) );
731 4 : return NULL;
732 : }
733 : }
734 :
735 : // ----------------------------------------------------------------
736 : // Create the header file with minimun information
737 : // ----------------------------------------------------------------
738 :
739 : const char *pszLDataType;
740 :
741 18 : switch( eType )
742 : {
743 : case GDT_Byte:
744 5 : if( nBands == 1 )
745 2 : pszLDataType = rstBYTE;
746 : else
747 3 : pszLDataType = rstRGB24;
748 5 : break;
749 : case GDT_Int16:
750 2 : pszLDataType = rstINTEGER;
751 2 : break;
752 : case GDT_Float32:
753 3 : pszLDataType = rstREAL;
754 3 : break;
755 : default:
756 : CPLError( CE_Failure, CPLE_AppDefined,
757 : "Attempt to create IDRISI dataset with an illegal "
758 : "data type(%s).\n",
759 8 : GDALGetDataTypeName( eType ) );
760 8 : return NULL;
761 :
762 : };
763 :
764 : char **papszLRDC;
765 :
766 10 : papszLRDC = NULL;
767 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_FORMAT, rstVERSION );
768 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_TITLE, "" );
769 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcDATA_TYPE, pszLDataType );
770 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_TYPE, "binary" );
771 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcCOLUMNS, CPLSPrintf( "%d", nXSize ) );
772 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcROWS, CPLSPrintf( "%d", nYSize ) );
773 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcREF_SYSTEM, "plane" );
774 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcREF_UNITS, "m" );
775 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcUNIT_DIST, "1" );
776 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcMIN_X, "0" );
777 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcMAX_X, CPLSPrintf( "%d", nXSize ) );
778 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcMIN_Y, "0" );
779 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcMAX_Y, CPLSPrintf( "%d", nYSize ) );
780 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcPOSN_ERROR, "unspecified" );
781 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcRESOLUTION, "1.0" );
782 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcMIN_VALUE, "0" );
783 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcMAX_VALUE, "0" );
784 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcDISPLAY_MIN, "0" );
785 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcDISPLAY_MAX, "0" );
786 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcVALUE_UNITS, "unspecified" );
787 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcVALUE_ERROR, "unspecified" );
788 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcFLAG_VALUE, "none" );
789 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcFLAG_DEFN, "none" );
790 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcLEGEND_CATS, "0" );
791 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcLINEAGES, "" );
792 10 : papszLRDC = CSLAddNameValue( papszLRDC, rdcCOMMENTS, "" );
793 :
794 : const char *pszLDocFilename;
795 10 : pszLDocFilename = CPLResetExtension( pszFilename, extRDC );
796 :
797 10 : CSLSetNameValueSeparator( papszLRDC, ": " );
798 10 : SaveAsCRLF( papszLRDC, pszLDocFilename );
799 10 : CSLDestroy( papszLRDC );
800 :
801 : // ----------------------------------------------------------------
802 : // Create an empty data file
803 : // ----------------------------------------------------------------
804 :
805 : FILE *fp;
806 :
807 10 : fp = VSIFOpenL( pszFilename, "wb+" );
808 :
809 10 : if( fp == NULL )
810 : {
811 : CPLError( CE_Failure, CPLE_OpenFailed,
812 0 : "Attempt to create file %s' failed.\n", pszFilename );
813 0 : return NULL;
814 : }
815 10 : VSIFCloseL( fp );
816 :
817 10 : return (IdrisiDataset *) GDALOpen( pszFilename, GA_Update );
818 : }
819 :
820 : /************************************************************************/
821 : /* CreateCopy() */
822 : /************************************************************************/
823 :
824 17 : GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
825 : GDALDataset *poSrcDS,
826 : int bStrict,
827 : char **papszOptions,
828 : GDALProgressFunc pfnProgress,
829 : void *pProgressData )
830 : {
831 17 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
832 0 : return NULL;
833 :
834 : // ------------------------------------------------------------------------
835 : // Check number of bands
836 : // ------------------------------------------------------------------------
837 :
838 17 : if ( ( ( poSrcDS->GetRasterCount() == 1 ) ||
839 : ( ( poSrcDS->GetRasterCount() == 3 ) &&
840 : ( ( poSrcDS->GetRasterBand( 1 )->GetRasterDataType() == GDT_Byte ) &&
841 : ( poSrcDS->GetRasterBand( 2 )->GetRasterDataType() == GDT_Byte ) &&
842 : ( poSrcDS->GetRasterBand( 3 )->GetRasterDataType() == GDT_Byte ) ) ) ) == FALSE )
843 : {
844 :
845 : CPLError( CE_Failure, CPLE_AppDefined,
846 : "Attempt to create IDRISI dataset with an illegal "
847 : "number of bands(%d).\n",
848 4 : poSrcDS->GetRasterCount() );
849 4 : return NULL;
850 : }
851 :
852 : // ------------------------------------------------------------------------
853 : // Check Data types
854 : // ------------------------------------------------------------------------
855 :
856 : int i;
857 :
858 22 : for( i = 1; i <= poSrcDS->GetRasterCount(); i++ )
859 : {
860 17 : GDALDataType eType = poSrcDS->GetRasterBand( i )->GetRasterDataType();
861 :
862 17 : if( bStrict )
863 : {
864 14 : if( eType != GDT_Byte &&
865 : eType != GDT_Int16 &&
866 : eType != GDT_Float32 )
867 : {
868 : CPLError( CE_Failure, CPLE_AppDefined,
869 : "Attempt to create IDRISI dataset in strict mode "
870 : "with an illegal data type(%s).\n",
871 8 : GDALGetDataTypeName( eType ) );
872 8 : return NULL;
873 : }
874 : }
875 : else
876 : {
877 3 : if( eType != GDT_Byte &&
878 : eType != GDT_Int16 &&
879 : eType != GDT_UInt16 &&
880 : eType != GDT_UInt32 &&
881 : eType != GDT_Int32 &&
882 : eType != GDT_Float32 &&
883 : eType != GDT_Float64 )
884 : {
885 : CPLError( CE_Failure, CPLE_AppDefined,
886 : "Attempt to create IDRISI dataset with an illegal "
887 : "data type(%s).\n",
888 0 : GDALGetDataTypeName( eType ) );
889 0 : return NULL;
890 : }
891 : }
892 : }
893 :
894 : // --------------------------------------------------------------------
895 : // Define data type
896 : // --------------------------------------------------------------------
897 :
898 5 : GDALRasterBand *poBand = poSrcDS->GetRasterBand( 1 );
899 5 : GDALDataType eType = poBand->GetRasterDataType();
900 :
901 5 : int bSuccessMin = FALSE;
902 5 : int bSuccessMax = FALSE;
903 :
904 : double dfMin;
905 : double dfMax;
906 :
907 5 : dfMin = poBand->GetMinimum( &bSuccessMin );
908 5 : dfMax = poBand->GetMaximum( &bSuccessMax );
909 :
910 5 : if( ! ( bSuccessMin && bSuccessMax ) )
911 : {
912 5 : poBand->GetStatistics( false, false, &dfMin, &dfMax, NULL, NULL );
913 : }
914 :
915 5 : if(!( ( eType == GDT_Byte ) ||
916 : ( eType == GDT_Int16 ) ||
917 : ( eType == GDT_Float32 ) ) )
918 : {
919 0 : if( eType == GDT_Float64 )
920 : {
921 0 : eType = GDT_Float32;
922 : }
923 : else
924 : {
925 0 : if( ( dfMin < (double) SHRT_MIN ) ||
926 : ( dfMax > (double) SHRT_MAX ) )
927 : {
928 0 : eType = GDT_Float32;
929 : }
930 : else
931 : {
932 0 : eType = GDT_Int16;
933 : }
934 : }
935 : }
936 :
937 : // --------------------------------------------------------------------
938 : // Create the dataset
939 : // --------------------------------------------------------------------
940 :
941 : IdrisiDataset *poDS;
942 :
943 : poDS = (IdrisiDataset *) IdrisiDataset::Create( pszFilename,
944 : poSrcDS->GetRasterXSize(),
945 : poSrcDS->GetRasterYSize(),
946 : poSrcDS->GetRasterCount(),
947 : eType,
948 5 : papszOptions );
949 :
950 5 : if( poDS == NULL )
951 4 : return NULL;
952 :
953 : // --------------------------------------------------------------------
954 : // Copy information to the dataset
955 : // --------------------------------------------------------------------
956 :
957 : double adfGeoTransform[6];
958 :
959 1 : poDS->SetProjection( poSrcDS->GetProjectionRef() );
960 :
961 1 : if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
962 : {
963 1 : poDS->SetGeoTransform( adfGeoTransform );
964 : }
965 : else
966 : {
967 0 : CSLSetNameValue( poDS->papszRDC, rdcMIN_X, CPLSPrintf( "%.1f", -0.5 ));
968 : CSLSetNameValue( poDS->papszRDC, rdcMAX_X, CPLSPrintf( "%.1f",
969 0 : poSrcDS->GetRasterXSize() - 0.5 ) );
970 : CSLSetNameValue( poDS->papszRDC, rdcMIN_Y, CPLSPrintf( "%.1f",
971 0 : poSrcDS->GetRasterYSize() + 0.5 ) );
972 0 : CSLSetNameValue( poDS->papszRDC, rdcMAX_Y, CPLSPrintf( "%.1f", 0.5 ));
973 0 : CSLSetNameValue( poDS->papszRDC, rdcRESOLUTION, "1" );
974 : }
975 :
976 : // --------------------------------------------------------------------
977 : // Copy information to the raster band
978 : // --------------------------------------------------------------------
979 :
980 : GDALRasterBand *poSrcBand;
981 : int bHasNoDataValue;
982 : double dfNoDataValue;
983 :
984 4 : for( i = 1; i <= poDS->nBands; i++ )
985 : {
986 3 : poSrcBand = poSrcDS->GetRasterBand( i );
987 3 : poBand = poDS->GetRasterBand( i );
988 :
989 3 : if( poDS->nBands == 1 )
990 : {
991 0 : poBand->SetUnitType( poSrcBand->GetUnitType() );
992 0 : poBand->SetColorTable( poSrcBand->GetColorTable() );
993 0 : poBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
994 :
995 0 : const GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
996 :
997 0 : if( poRAT != NULL )
998 : {
999 0 : poBand->SetDefaultRAT( poRAT );
1000 : }
1001 : }
1002 :
1003 3 : dfMin = poSrcBand->GetMinimum( NULL );
1004 3 : dfMax = poSrcBand->GetMaximum( NULL );
1005 3 : poBand->SetStatistics( dfMin, dfMax, 0.0, 0.0 );
1006 3 : dfNoDataValue = poSrcBand->GetNoDataValue( &bHasNoDataValue );
1007 3 : if( bHasNoDataValue )
1008 0 : poBand->SetNoDataValue( dfNoDataValue );
1009 : }
1010 :
1011 : // --------------------------------------------------------------------
1012 : // Copy image data
1013 : // --------------------------------------------------------------------
1014 :
1015 : GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
1016 : (GDALDatasetH) poDS, NULL,
1017 1 : pfnProgress, pProgressData );
1018 :
1019 : // --------------------------------------------------------------------
1020 : // Finalize
1021 : // --------------------------------------------------------------------
1022 :
1023 1 : poDS->FlushCache();
1024 :
1025 1 : return poDS;
1026 : }
1027 :
1028 : /************************************************************************/
1029 : /* GetFileList() */
1030 : /************************************************************************/
1031 :
1032 2 : char **IdrisiDataset::GetFileList()
1033 : {
1034 2 : char **papszFileList = GDALPamDataset::GetFileList();
1035 : const char *pszAssociated;
1036 :
1037 : // --------------------------------------------------------------------
1038 : // Symbol table file
1039 : // --------------------------------------------------------------------
1040 :
1041 2 : pszAssociated = CPLResetExtension( pszFilename, extSMP );
1042 :
1043 2 : if( FileExists( pszAssociated ) )
1044 : {
1045 0 : papszFileList = CSLAddString( papszFileList, pszAssociated );
1046 : }
1047 : else
1048 : {
1049 2 : pszAssociated = CPLResetExtension( pszFilename, extSMPu );
1050 :
1051 2 : if( FileExists( pszAssociated ) )
1052 : {
1053 0 : papszFileList = CSLAddString( papszFileList, pszAssociated );
1054 : }
1055 : }
1056 :
1057 : // --------------------------------------------------------------------
1058 : // Documentation file
1059 : // --------------------------------------------------------------------
1060 :
1061 2 : pszAssociated = CPLResetExtension( pszFilename, extRDC );
1062 :
1063 2 : if( FileExists( pszAssociated ) )
1064 : {
1065 2 : papszFileList = CSLAddString( papszFileList, pszAssociated );
1066 : }
1067 : else
1068 : {
1069 0 : pszAssociated = CPLResetExtension( pszFilename, extRDCu );
1070 :
1071 0 : if( FileExists( pszAssociated ) )
1072 : {
1073 0 : papszFileList = CSLAddString( papszFileList, pszAssociated );
1074 : }
1075 : }
1076 :
1077 : // --------------------------------------------------------------------
1078 : // Reference file
1079 : // --------------------------------------------------------------------
1080 :
1081 2 : pszAssociated = CPLResetExtension( pszFilename, extREF );
1082 :
1083 2 : if( FileExists( pszAssociated ) )
1084 : {
1085 0 : papszFileList = CSLAddString( papszFileList, pszAssociated );
1086 : }
1087 : else
1088 : {
1089 2 : pszAssociated = CPLResetExtension( pszFilename, extREFu );
1090 :
1091 2 : if( FileExists( pszAssociated ) )
1092 : {
1093 0 : papszFileList = CSLAddString( papszFileList, pszAssociated );
1094 : }
1095 : }
1096 :
1097 2 : return papszFileList;
1098 : }
1099 :
1100 : /************************************************************************/
1101 : /* GetGeoTransform() */
1102 : /************************************************************************/
1103 :
1104 1 : CPLErr IdrisiDataset::GetGeoTransform( double * padfTransform )
1105 : {
1106 1 : if( GDALPamDataset::GetGeoTransform( padfTransform ) != CE_None )
1107 : {
1108 1 : memcpy( padfTransform, adfGeoTransform, sizeof( double ) * 6 );
1109 :
1110 1 : if( adfGeoTransform[0] == 0.0
1111 0 : && adfGeoTransform[1] == 1.0
1112 0 : && adfGeoTransform[2] == 0.0
1113 0 : && adfGeoTransform[3] == 0.0
1114 0 : && adfGeoTransform[4] == 0.0
1115 0 : && adfGeoTransform[5] == 1.0 )
1116 0 : return CE_Failure;
1117 : }
1118 :
1119 1 : return CE_None;
1120 : }
1121 :
1122 : /************************************************************************/
1123 : /* SetGeoTransform() */
1124 : /************************************************************************/
1125 :
1126 1 : CPLErr IdrisiDataset::SetGeoTransform( double * padfTransform )
1127 : {
1128 1 : if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
1129 : {
1130 : CPLError( CE_Failure, CPLE_AppDefined,
1131 : "Attempt to set rotated geotransform on Idrisi Raster file.\n"
1132 0 : "Idrisi Raster does not support rotation.\n" );
1133 0 : return CE_Failure;
1134 : }
1135 :
1136 : // --------------------------------------------------------------------
1137 : // Update the .rdc file
1138 : // --------------------------------------------------------------------
1139 :
1140 : double dfMinX, dfMaxX, dfMinY, dfMaxY, dfXPixSz, dfYPixSz;
1141 :
1142 1 : dfXPixSz = padfTransform[1];
1143 1 : dfYPixSz = padfTransform[5];
1144 1 : dfMinX = padfTransform[0];
1145 1 : dfMaxX = ( dfXPixSz * nRasterXSize ) + dfMinX;
1146 :
1147 1 : if( dfYPixSz < 0 )
1148 : {
1149 1 : dfMaxY = padfTransform[3];
1150 1 : dfMinY = ( dfYPixSz * nRasterYSize ) + padfTransform[3];
1151 : }
1152 : else
1153 : {
1154 0 : dfMaxY = ( dfYPixSz * nRasterYSize ) + padfTransform[3];
1155 0 : dfMinY = padfTransform[3];
1156 : }
1157 :
1158 1 : CSLSetNameValue( papszRDC, rdcMIN_X, CPLSPrintf( "%.7f", dfMinX ) );
1159 1 : CSLSetNameValue( papszRDC, rdcMAX_X, CPLSPrintf( "%.7f", dfMaxX ) );
1160 1 : CSLSetNameValue( papszRDC, rdcMIN_Y, CPLSPrintf( "%.7f", dfMinY ) );
1161 1 : CSLSetNameValue( papszRDC, rdcMAX_Y, CPLSPrintf( "%.7f", dfMaxY ) );
1162 1 : CSLSetNameValue( papszRDC, rdcRESOLUTION, CPLSPrintf( "%.7f", fabs( dfYPixSz ) ) );
1163 :
1164 : // --------------------------------------------------------------------
1165 : // Update the Dataset attribute
1166 : // --------------------------------------------------------------------
1167 :
1168 1 : memcpy( adfGeoTransform, padfTransform, sizeof( double ) * 6 );
1169 :
1170 1 : return CE_None;
1171 : }
1172 :
1173 : /************************************************************************/
1174 : /* GetProjectionRef() */
1175 : /************************************************************************/
1176 :
1177 1 : const char *IdrisiDataset::GetProjectionRef( void )
1178 : {
1179 1 : const char *pszPamSRS = GDALPamDataset::GetProjectionRef();
1180 :
1181 1 : if( pszPamSRS != NULL && strlen( pszPamSRS ) > 0 )
1182 0 : return pszPamSRS;
1183 :
1184 1 : if( pszProjection == NULL )
1185 : {
1186 1 : const char *pszRefSystem = CSLFetchNameValue( papszRDC, rdcREF_SYSTEM );
1187 1 : const char *pszRefUnit = CSLFetchNameValue( papszRDC, rdcREF_UNITS );
1188 :
1189 1 : GeoReference2Wkt( pszRefSystem, pszRefUnit, &pszProjection );
1190 : }
1191 1 : return pszProjection;
1192 : }
1193 :
1194 : /************************************************************************/
1195 : /* SetProjection() */
1196 : /************************************************************************/
1197 :
1198 1 : CPLErr IdrisiDataset::SetProjection( const char *pszProjString )
1199 : {
1200 1 : CPLFree( pszProjection );
1201 1 : pszProjection = CPLStrdup( pszProjString );
1202 1 : CPLErr eResult = CE_None;
1203 :
1204 1 : char *pszRefSystem = NULL;
1205 1 : char *pszRefUnit = NULL;
1206 :
1207 1 : eResult = Wkt2GeoReference( pszProjString, &pszRefSystem, &pszRefUnit );
1208 :
1209 1 : CSLSetNameValue( papszRDC, rdcREF_SYSTEM, pszRefSystem );
1210 1 : CSLSetNameValue( papszRDC, rdcREF_UNITS, pszRefUnit );
1211 :
1212 1 : CPLFree( pszRefSystem );
1213 1 : CPLFree( pszRefUnit );
1214 :
1215 1 : return eResult;
1216 : }
1217 :
1218 : /************************************************************************/
1219 : /* IdrisiRasterBand() */
1220 : /************************************************************************/
1221 :
1222 14 : IdrisiRasterBand::IdrisiRasterBand( IdrisiDataset *poDS,
1223 : int nBand,
1224 14 : GDALDataType eDataType )
1225 : {
1226 14 : this->poDS = poDS;
1227 14 : this->nBand = nBand;
1228 14 : this->eDataType = eDataType;
1229 14 : this->poDefaultRAT = NULL;
1230 14 : this->dfMinimum = 0.0;
1231 14 : this->dfMaximum = 0.0;
1232 14 : this->bFirstVal = true;
1233 :
1234 : // --------------------------------------------------------------------
1235 : // Set Dimension
1236 : // --------------------------------------------------------------------
1237 :
1238 14 : nBlockYSize = 1;
1239 14 : nBlockXSize = poDS->GetRasterXSize();
1240 :
1241 : // --------------------------------------------------------------------
1242 : // Get ready for reading and writing
1243 : // --------------------------------------------------------------------
1244 :
1245 14 : nRecordSize = poDS->GetRasterXSize() * GDALGetDataTypeSize( eDataType ) / 8;
1246 :
1247 14 : pabyScanLine = (GByte*) VSIMalloc2( nRecordSize, poDS->nBands );
1248 :
1249 14 : if( pabyScanLine == NULL )
1250 : {
1251 : CPLError(CE_Failure, CPLE_OutOfMemory,
1252 : "IdrisiRasterBand::IdrisiRasterBand : Out of memory (nRasterXSize = %d)",
1253 0 : poDS->GetRasterXSize());
1254 : }
1255 :
1256 14 : nRecordSize *= poDS->nBands;
1257 14 : }
1258 :
1259 : /************************************************************************/
1260 : /* ~IdrisiRasterBand() */
1261 : /************************************************************************/
1262 :
1263 28 : IdrisiRasterBand::~IdrisiRasterBand()
1264 : {
1265 14 : CPLFree( pabyScanLine );
1266 :
1267 14 : if( poDefaultRAT )
1268 : {
1269 0 : delete poDefaultRAT;
1270 : }
1271 28 : }
1272 :
1273 : /************************************************************************/
1274 : /* IReadBlock() */
1275 : /************************************************************************/
1276 :
1277 162 : CPLErr IdrisiRasterBand::IReadBlock( int nBlockXOff,
1278 : int nBlockYOff,
1279 : void *pImage )
1280 : {
1281 162 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1282 :
1283 162 : if( VSIFSeekL( poGDS->fp,
1284 : vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET ) < 0 )
1285 : {
1286 : CPLError( CE_Failure, CPLE_FileIO,
1287 : "Can't seek(%s) block with X offset %d and Y offset %d.\n%s",
1288 0 : poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
1289 0 : return CE_Failure;
1290 : }
1291 :
1292 162 : if( (int) VSIFReadL( pabyScanLine, 1, nRecordSize, poGDS->fp ) < nRecordSize )
1293 : {
1294 : CPLError( CE_Failure, CPLE_FileIO,
1295 : "Can't read(%s) block with X offset %d and Y offset %d.\n%s",
1296 0 : poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
1297 0 : return CE_Failure;
1298 : }
1299 :
1300 162 : if( poGDS->nBands == 3 )
1301 : {
1302 : int i, j;
1303 5100 : for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
1304 : {
1305 5000 : ( (GByte*) pImage )[i] = pabyScanLine[j];
1306 : }
1307 : }
1308 : else
1309 : {
1310 62 : memcpy( pImage, pabyScanLine, nRecordSize );
1311 : }
1312 :
1313 : #ifdef CPL_MSB
1314 : if( eDataType == GDT_Float32 )
1315 : GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
1316 : #endif
1317 :
1318 162 : return CE_None;
1319 : }
1320 :
1321 : /************************************************************************/
1322 : /* IWriteBlock() */
1323 : /************************************************************************/
1324 :
1325 170 : CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
1326 : int nBlockYOff,
1327 : void *pImage )
1328 : {
1329 170 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1330 :
1331 : #ifdef CPL_MSB
1332 : // Swap in input buffer if needed.
1333 : if( eDataType == GDT_Float32 )
1334 : GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
1335 : #endif
1336 :
1337 170 : if( poGDS->nBands == 1 )
1338 : {
1339 20 : memcpy( pabyScanLine, pImage, nRecordSize );
1340 : }
1341 : else
1342 : {
1343 150 : if( nBand > 1 )
1344 : {
1345 : VSIFSeekL( poGDS->fp,
1346 100 : vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET );
1347 100 : VSIFReadL( pabyScanLine, 1, nRecordSize, poGDS->fp );
1348 : }
1349 : int i, j;
1350 7650 : for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
1351 : {
1352 7500 : pabyScanLine[j] = ( (GByte *) pImage )[i];
1353 : }
1354 : }
1355 :
1356 : #ifdef CPL_MSB
1357 : // Swap input buffer back to original form.
1358 : if( eDataType == GDT_Float32 )
1359 : GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
1360 : #endif
1361 :
1362 170 : VSIFSeekL( poGDS->fp, vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET );
1363 :
1364 170 : if( (int) VSIFWriteL( pabyScanLine, 1, nRecordSize, poGDS->fp ) < nRecordSize )
1365 : {
1366 : CPLError( CE_Failure, CPLE_FileIO,
1367 : "Can't write(%s) block with X offset %d and Y offset %d.\n%s",
1368 0 : poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
1369 0 : return CE_Failure;
1370 : }
1371 :
1372 : // --------------------------------------------------------------------
1373 : // Store the first value as mimunm and maximum
1374 : // --------------------------------------------------------------------
1375 :
1376 170 : if( bFirstVal )
1377 : {
1378 4 : switch( eDataType )
1379 : {
1380 : case GDT_Float32:
1381 1 : dfMinimum = dfMaximum = (float) ((float*) pabyScanLine)[0];
1382 1 : break;
1383 : case GDT_Int16:
1384 0 : dfMinimum = dfMaximum = (float) ((GInt16*) pabyScanLine)[0];
1385 0 : break;
1386 : default:
1387 : dfMinimum = dfMaximum = (float) ((GByte*) pabyScanLine)[
1388 3 : poGDS->nBands == 1 ? 0 : 3 - this->nBand ];
1389 : }
1390 4 : bFirstVal = false;
1391 : }
1392 :
1393 : // --------------------------------------------------------------------
1394 : // Search for the minimum and maximum values
1395 : // --------------------------------------------------------------------
1396 :
1397 : int i, j;
1398 :
1399 170 : if( eDataType == GDT_Float32 )
1400 : {
1401 420 : for( i = 0; i < nBlockXSize; i++ )
1402 : {
1403 400 : dfMinimum = MIN( dfMinimum, ((float*) pabyScanLine)[i] );
1404 400 : dfMaximum = MAX( dfMaximum, ((float*) pabyScanLine)[i] );
1405 : }
1406 : }
1407 150 : else if( eDataType == GDT_Int16 )
1408 : {
1409 0 : for( i = 0; i < nBlockXSize; i++ )
1410 : {
1411 0 : dfMinimum = MIN( dfMinimum, ((GInt16*) pabyScanLine)[i] );
1412 0 : dfMaximum = MAX( dfMaximum, ((GInt16*) pabyScanLine)[i] );
1413 : }
1414 : }
1415 150 : else if( poGDS->nBands == 1 )
1416 : {
1417 0 : for( i = 0; i < nBlockXSize; i++ )
1418 : {
1419 0 : dfMinimum = MIN( dfMinimum, ((GByte*) pabyScanLine)[i] );
1420 0 : dfMaximum = MAX( dfMaximum, ((GByte*) pabyScanLine)[i] );
1421 : }
1422 : }
1423 : else
1424 : {
1425 7650 : for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
1426 : {
1427 7500 : dfMinimum = MIN( dfMinimum, ((GByte*) pabyScanLine)[j] );
1428 7500 : dfMaximum = MAX( dfMaximum, ((GByte*) pabyScanLine)[j] );
1429 : }
1430 : }
1431 :
1432 170 : return CE_None;
1433 : }
1434 :
1435 : /************************************************************************/
1436 : /* GetMinimum() */
1437 : /************************************************************************/
1438 :
1439 0 : double IdrisiRasterBand::GetMinimum( int *pbSuccess )
1440 : {
1441 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1442 :
1443 : double adfMinValue[3];
1444 : sscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ), "%lf %lf %lf",
1445 0 : &adfMinValue[0], &adfMinValue[1], &adfMinValue[2] );
1446 :
1447 0 : if( pbSuccess )
1448 : {
1449 0 : *pbSuccess = true;
1450 : }
1451 :
1452 0 : return adfMinValue[this->nBand - 1];
1453 : }
1454 :
1455 : /************************************************************************/
1456 : /* GetMaximum() */
1457 : /************************************************************************/
1458 :
1459 0 : double IdrisiRasterBand::GetMaximum( int *pbSuccess )
1460 : {
1461 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1462 :
1463 : double adfMaxValue[3];
1464 : sscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ), "%lf %lf %lf",
1465 0 : &adfMaxValue[0], &adfMaxValue[1], &adfMaxValue[2] );
1466 :
1467 0 : if( pbSuccess )
1468 : {
1469 0 : *pbSuccess = true;
1470 : }
1471 :
1472 0 : return adfMaxValue[this->nBand - 1];
1473 : }
1474 :
1475 : /************************************************************************/
1476 : /* GetNoDataValue() */
1477 : /************************************************************************/
1478 :
1479 4 : double IdrisiRasterBand::GetNoDataValue( int *pbSuccess )
1480 : {
1481 4 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1482 :
1483 : double dfNoData;
1484 : const char *pszFlagDefn;
1485 :
1486 4 : if( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN ) != NULL )
1487 4 : pszFlagDefn = CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN );
1488 0 : else if( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN2 ) != NULL )
1489 0 : pszFlagDefn = CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN2 );
1490 : else
1491 0 : pszFlagDefn = CPLStrdup( "none" );
1492 :
1493 : // ------------------------------------------------------------------------
1494 : // If Flag_Def is not "none", Flag_Value means "background"
1495 : // or "missing data"
1496 : // ------------------------------------------------------------------------
1497 :
1498 4 : if( ! EQUAL( pszFlagDefn, "none" ) )
1499 : {
1500 0 : dfNoData = atof_nz( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_VALUE ) );
1501 0 : if( pbSuccess )
1502 0 : *pbSuccess = TRUE;
1503 : }
1504 : else
1505 : {
1506 4 : dfNoData = -9999.0; /* this value should be ignored */
1507 4 : if( pbSuccess )
1508 4 : *pbSuccess = FALSE;
1509 : }
1510 :
1511 4 : return dfNoData;
1512 : }
1513 :
1514 : /************************************************************************/
1515 : /* SetNoDataValue() */
1516 : /************************************************************************/
1517 :
1518 0 : CPLErr IdrisiRasterBand::SetNoDataValue( double dfNoDataValue )
1519 : {
1520 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1521 :
1522 : poGDS->papszRDC =
1523 0 : CSLSetNameValue( poGDS->papszRDC, rdcFLAG_VALUE, CPLSPrintf( "%.7g", dfNoDataValue ) );
1524 : poGDS->papszRDC =
1525 0 : CSLSetNameValue( poGDS->papszRDC, rdcFLAG_DEFN, "missing data" );
1526 :
1527 0 : return CE_None;
1528 : }
1529 :
1530 : /************************************************************************/
1531 : /* GetColorInterpretation() */
1532 : /************************************************************************/
1533 :
1534 0 : GDALColorInterp IdrisiRasterBand::GetColorInterpretation()
1535 : {
1536 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1537 :
1538 0 : if( poGDS->nBands == 3 )
1539 : {
1540 0 : switch( nBand )
1541 : {
1542 0 : case 1: return GCI_BlueBand;
1543 0 : case 2: return GCI_GreenBand;
1544 0 : case 3: return GCI_RedBand;
1545 : }
1546 : }
1547 0 : else if( poGDS->poColorTable->GetColorEntryCount() > 0 )
1548 : {
1549 0 : return GCI_PaletteIndex;
1550 : }
1551 0 : return GCI_GrayIndex;
1552 : }
1553 :
1554 : /************************************************************************/
1555 : /* GetCategoryNames() */
1556 : /************************************************************************/
1557 :
1558 0 : char **IdrisiRasterBand::GetCategoryNames()
1559 : {
1560 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1561 :
1562 0 : return poGDS->papszCategories;
1563 : }
1564 :
1565 : /************************************************************************/
1566 : /* SetCategoryNames() */
1567 : /************************************************************************/
1568 :
1569 0 : CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
1570 : {
1571 0 : int nCatCount = CSLCount( papszCategoryNames );
1572 :
1573 0 : if( nCatCount == 0 )
1574 0 : return CE_None;
1575 :
1576 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1577 :
1578 0 : CSLDestroy( poGDS->papszCategories );
1579 0 : poGDS->papszCategories = CSLDuplicate( papszCategoryNames );
1580 :
1581 : // ------------------------------------------------------
1582 : // Search for the "Legend cats : N" line
1583 : // ------------------------------------------------------
1584 :
1585 0 : int i, nLine = -1;
1586 0 : for( i = 0;( i < CSLCount( poGDS->papszRDC ) ) &&( nLine == -1 ); i++ )
1587 0 : if( EQUALN( poGDS->papszRDC[i], rdcLEGEND_CATS, 12 ) )
1588 0 : nLine = i;
1589 :
1590 0 : if( nLine < 0 )
1591 0 : return CE_None;
1592 :
1593 0 : int nCount = atoi_nz( CSLFetchNameValue( poGDS->papszRDC, rdcLEGEND_CATS ) );
1594 :
1595 : // ------------------------------------------------------
1596 : // Delte old instance of the categoty names
1597 : // ------------------------------------------------------
1598 :
1599 0 : if( nCount > 0 )
1600 0 : poGDS->papszRDC = CSLRemoveStrings( poGDS->papszRDC, nLine + 1, nCount, NULL );
1601 :
1602 0 : nCount = 0;
1603 :
1604 0 : for( i = 0; i < nCatCount; i++ )
1605 : {
1606 0 : if( ( strlen( papszCategoryNames[i] ) > 0 ) )
1607 : {
1608 : poGDS->papszRDC = CSLInsertString( poGDS->papszRDC,( nLine + nCount + 1 ),
1609 0 : CPLSPrintf( "%s:%s", CPLSPrintf( rdcCODE_N, i ), papszCategoryNames[i] ) );
1610 0 : nCount++;
1611 : }
1612 : }
1613 :
1614 0 : CSLSetNameValue( poGDS->papszRDC, rdcLEGEND_CATS, CPLSPrintf( "%d", nCount ) );
1615 :
1616 0 : return CE_None;
1617 : }
1618 :
1619 : /************************************************************************/
1620 : /* GetColorTable() */
1621 : /************************************************************************/
1622 :
1623 0 : GDALColorTable *IdrisiRasterBand::GetColorTable()
1624 : {
1625 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1626 :
1627 0 : if( poGDS->poColorTable->GetColorEntryCount() == 0 )
1628 : {
1629 0 : return NULL;
1630 : }
1631 : else
1632 : {
1633 0 : return poGDS->poColorTable;
1634 : }
1635 : }
1636 :
1637 : /************************************************************************/
1638 : /* SetColorTable() */
1639 : /************************************************************************/
1640 :
1641 0 : CPLErr IdrisiRasterBand::SetColorTable( GDALColorTable *poColorTable )
1642 : {
1643 0 : if( poColorTable == NULL )
1644 : {
1645 0 : return CE_None;
1646 : }
1647 :
1648 0 : if( poColorTable->GetColorEntryCount() == 0 )
1649 : {
1650 0 : return CE_None;
1651 : }
1652 :
1653 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1654 :
1655 0 : delete poGDS->poColorTable;
1656 :
1657 0 : poGDS->poColorTable = poColorTable->Clone();
1658 :
1659 : const char *pszSMPFilename;
1660 0 : pszSMPFilename = CPLResetExtension( poGDS->pszFilename, extSMP );
1661 : FILE *fpSMP;
1662 :
1663 0 : if( ( fpSMP = VSIFOpenL( pszSMPFilename, "w" ) ) != NULL )
1664 : {
1665 0 : VSIFWriteL( "[Idrisi]", 8, 1, fpSMP );
1666 0 : GByte nPlatform = 1; VSIFWriteL( &nPlatform, 1, 1, fpSMP );
1667 0 : GByte nVersion = 11; VSIFWriteL( &nVersion, 1, 1, fpSMP );
1668 0 : GByte nDepth = 8; VSIFWriteL( &nDepth, 1, 1, fpSMP );
1669 0 : GByte nHeadSz = 18; VSIFWriteL( &nHeadSz, 1, 1, fpSMP );
1670 0 : GUInt16 nCount = 255; VSIFWriteL( &nCount, 2, 1, fpSMP );
1671 0 : GUInt16 nMix = 0; VSIFWriteL( &nMix, 2, 1, fpSMP );
1672 0 : GUInt16 nMax = 255; VSIFWriteL( &nMax, 2, 1, fpSMP );
1673 :
1674 : GDALColorEntry oEntry;
1675 : GByte aucRGB[3];
1676 : int i;
1677 :
1678 0 : for( i = 0; i < poColorTable->GetColorEntryCount(); i++ )
1679 : {
1680 0 : poColorTable->GetColorEntryAsRGB( i, &oEntry );
1681 0 : aucRGB[0] = (GByte) oEntry.c1;
1682 0 : aucRGB[1] = (GByte) oEntry.c2;
1683 0 : aucRGB[2] = (GByte) oEntry.c3;
1684 0 : VSIFWriteL( &aucRGB, 3, 1, fpSMP );
1685 : }
1686 : /* smp files always have 256 occurences */
1687 0 : for( i = poColorTable->GetColorEntryCount(); i <= 255; i++ )
1688 : {
1689 0 : poColorTable->GetColorEntryAsRGB( i, &oEntry );
1690 0 : aucRGB[0] = (GByte) 0;
1691 0 : aucRGB[1] = (GByte) 0;
1692 0 : aucRGB[2] = (GByte) 0;
1693 0 : VSIFWriteL( &aucRGB, 3, 1, fpSMP );
1694 : }
1695 0 : VSIFCloseL( fpSMP );
1696 : }
1697 :
1698 0 : return CE_None;
1699 : }
1700 :
1701 : /************************************************************************/
1702 : /* GetUnitType() */
1703 : /************************************************************************/
1704 :
1705 0 : const char *IdrisiRasterBand::GetUnitType()
1706 : {
1707 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1708 :
1709 0 : return poGDS->pszUnitType;
1710 : }
1711 :
1712 : /************************************************************************/
1713 : /* SetUnitType() */
1714 : /************************************************************************/
1715 :
1716 0 : CPLErr IdrisiRasterBand::SetUnitType( const char *pszUnitType )
1717 : {
1718 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1719 :
1720 0 : if( strlen( pszUnitType ) == 0 )
1721 : {
1722 : poGDS->papszRDC =
1723 0 : CSLSetNameValue( poGDS->papszRDC, rdcVALUE_UNITS, "unspecified" );
1724 : }
1725 : else
1726 : {
1727 : poGDS->papszRDC =
1728 0 : CSLSetNameValue( poGDS->papszRDC, rdcVALUE_UNITS, pszUnitType );
1729 : }
1730 :
1731 0 : return CE_None;
1732 : }
1733 :
1734 : /************************************************************************/
1735 : /* SetStatistics() */
1736 : /************************************************************************/
1737 :
1738 7 : CPLErr IdrisiRasterBand::SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev )
1739 : {
1740 7 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1741 :
1742 7 : double adfMin[3] = {0.0, 0.0, 0.0};
1743 7 : double adfMax[3] = {0.0, 0.0, 0.0};
1744 :
1745 7 : sscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ), "%lf %lf %lf", &adfMin[0], &adfMin[1], &adfMin[2] );
1746 7 : sscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ), "%lf %lf %lf", &adfMax[0], &adfMax[1], &adfMax[2] );
1747 :
1748 7 : adfMin[nBand - 1] = dfMin;
1749 7 : adfMax[nBand - 1] = dfMax;
1750 :
1751 7 : if( poGDS->nBands == 3 )
1752 : {
1753 : poGDS->papszRDC =
1754 6 : CSLSetNameValue( poGDS->papszRDC, rdcMIN_VALUE, CPLSPrintf( "%.8g %.8g %.8g", adfMin[0], adfMin[1], adfMin[2] ) );
1755 : poGDS->papszRDC =
1756 6 : CSLSetNameValue( poGDS->papszRDC, rdcMAX_VALUE, CPLSPrintf( "%.8g %.8g %.8g", adfMax[0], adfMax[1], adfMax[2] ) );
1757 : poGDS->papszRDC =
1758 6 : CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MIN, CPLSPrintf( "%.8g %.8g %.8g", adfMin[0], adfMin[1], adfMin[2] ) );
1759 : poGDS->papszRDC =
1760 6 : CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MAX, CPLSPrintf( "%.8g %.8g %.8g", adfMax[0], adfMax[1], adfMax[2] ) );
1761 : }
1762 : else
1763 : {
1764 : poGDS->papszRDC =
1765 1 : CSLSetNameValue( poGDS->papszRDC, rdcMIN_VALUE, CPLSPrintf( "%.8g", adfMin[0] ) );
1766 : poGDS->papszRDC =
1767 1 : CSLSetNameValue( poGDS->papszRDC, rdcMAX_VALUE, CPLSPrintf( "%.8g", adfMax[0] ) );
1768 : poGDS->papszRDC =
1769 1 : CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MIN, CPLSPrintf( "%.8g", adfMin[0] ) );
1770 : poGDS->papszRDC =
1771 1 : CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MAX, CPLSPrintf( "%.8g", adfMax[0] ) );
1772 : }
1773 :
1774 7 : return GDALRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
1775 : }
1776 :
1777 : /************************************************************************/
1778 : /* SetDefaultRAT() */
1779 : /************************************************************************/
1780 :
1781 0 : CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
1782 : {
1783 0 : if( ! poRAT )
1784 : {
1785 0 : return CE_Failure;
1786 : }
1787 :
1788 : // ----------------------------------------------------------
1789 : // Get field indecies
1790 : // ----------------------------------------------------------
1791 :
1792 0 : int iValue = -1;
1793 0 : int iRed = poRAT->GetColOfUsage( GFU_Red );
1794 0 : int iGreen = poRAT->GetColOfUsage( GFU_Green );
1795 0 : int iBlue = poRAT->GetColOfUsage( GFU_Blue );
1796 0 : int iName = -1;
1797 : int i;
1798 :
1799 0 : GDALColorTable *poCT = NULL;
1800 0 : char **papszNames = NULL;
1801 :
1802 0 : int nFact = 1;
1803 :
1804 : // ----------------------------------------------------------
1805 : // Seek for "Value" field index (AGIS standards field name)
1806 : // ----------------------------------------------------------
1807 :
1808 0 : if( GetColorTable() == 0 || GetColorTable()->GetColorEntryCount() == 0 )
1809 : {
1810 0 : for( i = 0; i < poRAT->GetColumnCount(); i++ )
1811 : {
1812 0 : if EQUALN( "Value", poRAT->GetNameOfCol( i ), 5 )
1813 : {
1814 0 : iValue = i;
1815 0 : break;
1816 : }
1817 : }
1818 :
1819 0 : if( iRed != -1 && iGreen != -1 && iBlue != -1 )
1820 : {
1821 0 : poCT = new GDALColorTable();
1822 0 : nFact = poRAT->GetTypeOfCol( iRed ) == GFT_Real ? 255 : 1;
1823 : }
1824 : }
1825 :
1826 : // ----------------------------------------------------------
1827 : // Seek for Name field index
1828 : // ----------------------------------------------------------
1829 :
1830 0 : if( GetCategoryNames() == 0 || CSLCount( GetCategoryNames() ) == 0 )
1831 : {
1832 0 : iName = poRAT->GetColOfUsage( GFU_Name );
1833 0 : if( iName == -1 )
1834 : {
1835 0 : for( i = 0; i < poRAT->GetColumnCount(); i++ )
1836 : {
1837 0 : if EQUALN( "Class_Name", poRAT->GetNameOfCol( i ), 10 )
1838 : {
1839 0 : iName = i;
1840 0 : break;
1841 : }
1842 0 : else if EQUALN( "Categor", poRAT->GetNameOfCol( i ), 7 )
1843 : {
1844 0 : iName = i;
1845 0 : break;
1846 : }
1847 0 : else if EQUALN( "Name", poRAT->GetNameOfCol( i ), 4 )
1848 : {
1849 0 : iName = i;
1850 0 : break;
1851 : }
1852 : }
1853 : }
1854 :
1855 : /* if still can't find it use the first String column */
1856 :
1857 0 : if( iName == -1 )
1858 : {
1859 0 : for( i = 0; i < poRAT->GetColumnCount(); i++ )
1860 : {
1861 0 : if( poRAT->GetTypeOfCol( i ) == GFT_String )
1862 : {
1863 0 : iName = i;
1864 0 : break;
1865 : }
1866 : }
1867 : }
1868 :
1869 : // ----------------------------------------------------------
1870 : // Incomplete Attribute Table;
1871 : // ----------------------------------------------------------
1872 :
1873 0 : if( iName == -1 )
1874 : {
1875 0 : iName = iValue;
1876 : }
1877 : }
1878 :
1879 : // ----------------------------------------------------------
1880 : // Initialization
1881 : // ----------------------------------------------------------
1882 :
1883 0 : double dRed = 0.0;
1884 0 : double dGreen = 0.0;
1885 0 : double dBlue = 0.0;
1886 :
1887 : // ----------------------------------------------------------
1888 : // Load values
1889 : // ----------------------------------------------------------
1890 :
1891 : GDALColorEntry sColor;
1892 0 : int iEntry = 0;
1893 0 : int iOut = 0;
1894 0 : int nEntryCount = poRAT->GetRowCount();
1895 0 : int nValue = 0;
1896 :
1897 0 : if( iValue != -1 )
1898 : {
1899 0 : nValue = poRAT->GetValueAsInt( iEntry, iValue );
1900 : }
1901 :
1902 0 : for( iOut = 0; iOut < 65535 && ( iEntry < nEntryCount ); iOut++ )
1903 : {
1904 0 : if( iOut == nValue )
1905 : {
1906 0 : if( poCT )
1907 : {
1908 0 : dRed = poRAT->GetValueAsDouble( iEntry, iRed );
1909 0 : dGreen = poRAT->GetValueAsDouble( iEntry, iGreen );
1910 0 : dBlue = poRAT->GetValueAsDouble( iEntry, iBlue );
1911 0 : sColor.c1 = (short) ( dRed * nFact );
1912 0 : sColor.c2 = (short) ( dGreen * nFact );
1913 0 : sColor.c3 = (short) ( dBlue * nFact );
1914 0 : sColor.c4 = (short) ( 255 / nFact );
1915 0 : poCT->SetColorEntry( iEntry, &sColor );
1916 : }
1917 :
1918 0 : if( iName != -1 )
1919 : {
1920 : papszNames = CSLAddString( papszNames,
1921 0 : poRAT->GetValueAsString( iEntry, iName ) );
1922 : }
1923 :
1924 : /* Advance on the table */
1925 :
1926 0 : if( ( ++iEntry ) < nEntryCount )
1927 : {
1928 0 : if( iValue != -1 )
1929 0 : nValue = poRAT->GetValueAsInt( iEntry, iValue );
1930 : else
1931 0 : nValue = iEntry;
1932 : }
1933 : }
1934 0 : else if( iOut < nValue )
1935 : {
1936 0 : if( poCT )
1937 : {
1938 0 : sColor.c1 = (short) 0;
1939 0 : sColor.c2 = (short) 0;
1940 0 : sColor.c3 = (short) 0;
1941 0 : sColor.c4 = (short) 255;
1942 0 : poCT->SetColorEntry( iEntry, &sColor );
1943 : }
1944 :
1945 0 : if( iName != -1 )
1946 0 : papszNames = CSLAddString( papszNames, "" );
1947 : }
1948 : }
1949 :
1950 : // ----------------------------------------------------------
1951 : // Set Color Table
1952 : // ----------------------------------------------------------
1953 :
1954 0 : if( poCT )
1955 : {
1956 0 : SetColorTable( poCT );
1957 0 : delete poCT;
1958 : }
1959 :
1960 : // ----------------------------------------------------------
1961 : // Update Category Names
1962 : // ----------------------------------------------------------
1963 :
1964 0 : if( papszNames )
1965 : {
1966 0 : SetCategoryNames( papszNames );
1967 0 : CSLDestroy( papszNames );
1968 : }
1969 :
1970 : // ----------------------------------------------------------
1971 : // Update Attribute Table
1972 : // ----------------------------------------------------------
1973 :
1974 0 : if( poDefaultRAT )
1975 : {
1976 0 : delete poDefaultRAT;
1977 : }
1978 :
1979 0 : poDefaultRAT = poRAT->Clone();
1980 :
1981 0 : return CE_None;
1982 : }
1983 :
1984 : /************************************************************************/
1985 : /* GetDefaultRAT() */
1986 : /************************************************************************/
1987 :
1988 0 : const GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
1989 : {
1990 0 : IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
1991 :
1992 0 : if( poGDS->papszCategories == NULL )
1993 : {
1994 0 : return NULL;
1995 : }
1996 :
1997 0 : bool bHasColorTable = poGDS->poColorTable->GetColorEntryCount() > 0;
1998 :
1999 : // ----------------------------------------------------------
2000 : // Create the bands Attribute Table
2001 : // ----------------------------------------------------------
2002 :
2003 0 : if( poDefaultRAT )
2004 : {
2005 0 : delete poDefaultRAT;
2006 : }
2007 :
2008 0 : poDefaultRAT = new GDALRasterAttributeTable();
2009 :
2010 : // ----------------------------------------------------------
2011 : // Create (Value, Red, Green, Blue, Alpha, Class_Name) fields
2012 : // ----------------------------------------------------------
2013 :
2014 0 : poDefaultRAT->CreateColumn( "Value", GFT_Integer, GFU_Generic );
2015 0 : poDefaultRAT->CreateColumn( "Value_1", GFT_Integer, GFU_MinMax );
2016 :
2017 0 : if( bHasColorTable )
2018 : {
2019 0 : poDefaultRAT->CreateColumn( "Red", GFT_Integer, GFU_Red );
2020 0 : poDefaultRAT->CreateColumn( "Green", GFT_Integer, GFU_Green );
2021 0 : poDefaultRAT->CreateColumn( "Blue", GFT_Integer, GFU_Blue );
2022 0 : poDefaultRAT->CreateColumn( "Alpha", GFT_Integer, GFU_Alpha );
2023 : }
2024 0 : poDefaultRAT->CreateColumn( "Class_name", GFT_String, GFU_Name );
2025 :
2026 : // ----------------------------------------------------------
2027 : // Loop throught the Category Names
2028 : // ----------------------------------------------------------
2029 :
2030 : GDALColorEntry sEntry;
2031 0 : int iName = poDefaultRAT->GetColOfUsage( GFU_Name );
2032 0 : int nEntryCount = CSLCount( poGDS->papszCategories );
2033 0 : int iEntry = 0;
2034 0 : int iRows = 0;
2035 :
2036 0 : for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
2037 : {
2038 0 : if EQUAL( poGDS->papszCategories[iEntry], "" )
2039 : {
2040 0 : continue; // Eliminate the empty ones
2041 : }
2042 0 : poDefaultRAT->SetRowCount( poDefaultRAT->GetRowCount() + 1 );
2043 0 : poDefaultRAT->SetValue( iRows, 0, iEntry );
2044 0 : poDefaultRAT->SetValue( iRows, 1, iEntry );
2045 0 : if( bHasColorTable )
2046 : {
2047 0 : poGDS->poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
2048 0 : poDefaultRAT->SetValue( iRows, 2, sEntry.c1 );
2049 0 : poDefaultRAT->SetValue( iRows, 3, sEntry.c2 );
2050 0 : poDefaultRAT->SetValue( iRows, 4, sEntry.c3 );
2051 0 : poDefaultRAT->SetValue( iRows, 5, sEntry.c4 );
2052 : }
2053 0 : poDefaultRAT->SetValue( iRows, iName, poGDS->papszCategories[iEntry] );
2054 0 : iRows++;
2055 : }
2056 :
2057 0 : return poDefaultRAT;
2058 : }
2059 :
2060 : /************************************************************************/
2061 : /* GeoReference2Wkt() */
2062 : /************************************************************************/
2063 :
2064 : /***
2065 : * Converts Idrisi geographic reference information to OpenGIS WKT.
2066 : *
2067 : * The Idrisi metadata file contain two fields that describe the
2068 : * geographic reference, RefSystem and RefUnit.
2069 : *
2070 : * RefSystem can contains the world "plane" or the name of a georeference
2071 : * file <refsystem>.ref that details the geographic reference
2072 : * system( coordinate system and projection parameters ). RefUnits
2073 : * indicates the unit of the image bounds.
2074 : *
2075 : * The georeference files are generally located in the product installation
2076 : * folder $IDRISIDIR\Georef, but they are first looked for in the same
2077 : * folder as the data file.
2078 : *
2079 : * If a Reference system names can be recognized by a name convention
2080 : * it will be interpreted without the need to read the georeference file.
2081 : * That includes "latlong" and all the UTM and State Plane zones.
2082 : *
2083 : * RefSystem "latlong" means that the data is not project and the coordinate
2084 : * system is WGS84. RefSystem "plane" means that the there is no coordinate
2085 : * system but the it is possible to calculate areas and distance by looking
2086 : * at the RefUnits.
2087 : *
2088 : * If the environment variable IDRISIDIR is not set and the georeference file
2089 : * need to be read then the projection string will result as unknown.
2090 : ***/
2091 :
2092 1 : CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
2093 : const char *pszRefUnits,
2094 : char **pszProjString )
2095 : {
2096 1 : OGRSpatialReference oSRS;
2097 :
2098 : // ---------------------------------------------------------
2099 : // Plane
2100 : // ---------------------------------------------------------
2101 :
2102 1 : if( EQUAL( pszRefSystem, rstPLANE ) )
2103 : {
2104 0 : oSRS.SetLocalCS( "Plane" );
2105 0 : int nUnit = GetUnitIndex( pszRefUnits );
2106 0 : if( nUnit > -1 )
2107 : {
2108 0 : int nDeft = aoLinearUnitsConv[nUnit].nDefaultG;
2109 : oSRS.SetLinearUnits( aoLinearUnitsConv[nDeft].pszName,
2110 0 : aoLinearUnitsConv[nDeft].dfConv );
2111 : }
2112 0 : oSRS.exportToWkt( pszProjString );
2113 0 : return CE_None;
2114 : }
2115 :
2116 : // ---------------------------------------------------------
2117 : // Latlong
2118 : // ---------------------------------------------------------
2119 :
2120 1 : if( EQUAL( pszRefSystem, rstLATLONG ) ||
2121 : EQUAL( pszRefSystem, rstLATLONG2 ) )
2122 : {
2123 1 : oSRS.SetWellKnownGeogCS( "WGS84" );
2124 1 : oSRS.exportToWkt( pszProjString );
2125 1 : return CE_None;
2126 : }
2127 :
2128 : // ---------------------------------------------------------
2129 : // Prepare for scanning in lower case
2130 : // ---------------------------------------------------------
2131 :
2132 : char *pszRefSystemLower;
2133 0 : pszRefSystemLower = CPLStrdup( pszRefSystem );
2134 0 : CPLStrlwr( pszRefSystemLower );
2135 :
2136 : // ---------------------------------------------------------
2137 : // UTM naming convention( ex.: utm-30n )
2138 : // ---------------------------------------------------------
2139 :
2140 0 : if( EQUALN( pszRefSystem, rstUTM, 3 ) )
2141 : {
2142 : int nZone;
2143 : char cNorth;
2144 0 : sscanf( pszRefSystemLower, rstUTM, &nZone, &cNorth );
2145 0 : oSRS.SetWellKnownGeogCS( "WGS84" );
2146 0 : oSRS.SetUTM( nZone,( cNorth == 'n' ) );
2147 0 : oSRS.exportToWkt( pszProjString );
2148 0 : CPLFree( pszRefSystemLower );
2149 0 : return CE_None;
2150 : }
2151 :
2152 : // ---------------------------------------------------------
2153 : // State Plane naming convention( ex.: spc83ma1 )
2154 : // ---------------------------------------------------------
2155 :
2156 0 : if( EQUALN( pszRefSystem, rstSPC, 3 ) )
2157 : {
2158 : int nNAD;
2159 : int nZone;
2160 : char szState[3];
2161 0 : sscanf( pszRefSystemLower, rstSPC, &nNAD, szState, &nZone );
2162 0 : int nSPCode = GetStateCode( szState );
2163 0 : if( nSPCode != -1 )
2164 : {
2165 0 : nZone = ( nZone == 1 ? nSPCode : nSPCode + nZone - 1 );
2166 :
2167 0 : if( oSRS.SetStatePlane( nZone, ( nNAD == 83 ) ) != OGRERR_FAILURE )
2168 : {
2169 0 : oSRS.exportToWkt( pszProjString );
2170 0 : CPLFree( pszRefSystemLower );
2171 0 : return CE_None;
2172 : }
2173 :
2174 : // ----------------------------------------------------------
2175 : // If SetStatePlane fails, set GeoCS as NAD Datum and let it
2176 : // try to read the projection info from georeference file( * )
2177 : // ----------------------------------------------------------
2178 :
2179 0 : oSRS.SetWellKnownGeogCS( CPLSPrintf( "NAD%d", nNAD ) );
2180 : }
2181 : }
2182 :
2183 0 : CPLFree( pszRefSystemLower );
2184 0 : pszRefSystemLower = NULL;
2185 :
2186 : // ------------------------------------------------------------------
2187 : // Search for georeference file <RefSystem>.ref
2188 : // ------------------------------------------------------------------
2189 :
2190 : const char *pszFName = CPLSPrintf( "%s%c%s.ref",
2191 0 : CPLGetDirname( pszFilename ), PATHDELIM, pszRefSystem );
2192 :
2193 0 : if( ! FileExists( pszFName ) )
2194 : {
2195 : // ------------------------------------------------------------------
2196 : // Look at $IDRISIDIR\Georef\<RefSystem>.ref
2197 : // ------------------------------------------------------------------
2198 :
2199 0 : const char *pszIdrisiDir = CPLGetConfigOption( "IDRISIDIR", NULL );
2200 :
2201 0 : if( ( pszIdrisiDir ) != NULL )
2202 : {
2203 : pszFName = CPLSPrintf( "%s%cgeoref%c%s.ref",
2204 0 : pszIdrisiDir, PATHDELIM, PATHDELIM, pszRefSystem );
2205 : }
2206 : }
2207 :
2208 : // ------------------------------------------------------------------
2209 : // Cannot find georeference file
2210 : // ------------------------------------------------------------------
2211 :
2212 0 : if( ! FileExists( pszFName ) )
2213 : {
2214 : CPLDebug( "RST", "Cannot find Idrisi georeference file %s",
2215 0 : pszRefSystem );
2216 :
2217 0 : if( oSRS.IsGeographic() == FALSE ) /* see State Plane remarks( * ) */
2218 : {
2219 0 : oSRS.SetLocalCS( "Unknown" );
2220 0 : int nUnit = GetUnitIndex( pszRefUnits );
2221 0 : if( nUnit > -1 )
2222 : {
2223 0 : int nDeft = aoLinearUnitsConv[nUnit].nDefaultG;
2224 : oSRS.SetLinearUnits( aoLinearUnitsConv[nDeft].pszName,
2225 0 : aoLinearUnitsConv[nDeft].dfConv );
2226 : }
2227 : }
2228 0 : oSRS.exportToWkt( pszProjString );
2229 0 : return CE_Failure;
2230 : }
2231 :
2232 : // ------------------------------------------------------------------
2233 : // Read values from georeference file
2234 : // ------------------------------------------------------------------
2235 :
2236 0 : char **papszRef = CSLLoad( pszFName );
2237 0 : CSLSetNameValueSeparator( papszRef, ":" );
2238 :
2239 : char *pszGeorefName;
2240 :
2241 0 : if( EQUAL( CSLFetchNameValue( papszRef, refREF_SYSTEM ), "" ) == FALSE )
2242 : {
2243 0 : pszGeorefName = CPLStrdup( CSLFetchNameValue( papszRef, refREF_SYSTEM ) );
2244 : }
2245 : else
2246 : {
2247 0 : pszGeorefName = CPLStrdup( CSLFetchNameValue( papszRef, refREF_SYSTEM2 ) );
2248 : }
2249 0 : char *pszProjName = CPLStrdup( CSLFetchNameValue( papszRef, refPROJECTION ) );
2250 0 : char *pszDatum = CPLStrdup( CSLFetchNameValue( papszRef, refDATUM ) );
2251 0 : char *pszEllipsoid = CPLStrdup( CSLFetchNameValue( papszRef, refELLIPSOID ) );
2252 0 : double dfCenterLat = atof_nz( CSLFetchNameValue( papszRef, refORIGIN_LAT ) );
2253 0 : double dfCenterLong = atof_nz( CSLFetchNameValue( papszRef, refORIGIN_LONG ) );
2254 0 : double dfSemiMajor = atof_nz( CSLFetchNameValue( papszRef, refMAJOR_SAX ) );
2255 0 : double dfSemiMinor = atof_nz( CSLFetchNameValue( papszRef, refMINOR_SAX ) );
2256 0 : double dfFalseEasting = atof_nz( CSLFetchNameValue( papszRef, refORIGIN_X ) );
2257 0 : double dfFalseNorthing = atof_nz( CSLFetchNameValue( papszRef, refORIGIN_Y ) );
2258 0 : double dfStdP1 = atof_nz( CSLFetchNameValue( papszRef, refSTANDL_1 ) );
2259 0 : double dfStdP2 = atof_nz( CSLFetchNameValue( papszRef, refSTANDL_2 ) );
2260 : double dfScale;
2261 : double adfToWGS84[3];
2262 :
2263 : sscanf( CSLFetchNameValue( papszRef, refDELTA_WGS84 ), "%lf %lf %lf",
2264 0 : &adfToWGS84[0], &adfToWGS84[1], &adfToWGS84[2] );
2265 :
2266 0 : if( EQUAL( CSLFetchNameValue( papszRef, refSCALE_FAC ), "na" ) )
2267 0 : dfScale = 1.0;
2268 : else
2269 0 : dfScale = atof_nz( CSLFetchNameValue( papszRef, refSCALE_FAC ) );
2270 :
2271 0 : CSLDestroy( papszRef );
2272 :
2273 : // ----------------------------------------------------------------------
2274 : // Set the Geographic Coordinate System
2275 : // ----------------------------------------------------------------------
2276 :
2277 0 : if( oSRS.IsGeographic() == FALSE ) /* see State Plane remarks(*) */
2278 : {
2279 0 : int nEPSG = 0;
2280 :
2281 : // ----------------------------------------------------------------------
2282 : // Is it a WGS84 equivalent?
2283 : // ----------------------------------------------------------------------
2284 :
2285 0 : if( ( EQUALN( pszEllipsoid, "WGS", 3 ) ) &&( strstr( pszEllipsoid, "84" ) ) &&
2286 : ( EQUALN( pszDatum, "WGS", 3 ) ) &&( strstr( pszDatum, "84" ) ) &&
2287 0 : ( adfToWGS84[0] == 0.0 ) &&( adfToWGS84[1] == 0.0 ) &&( adfToWGS84[2] == 0.0 ) )
2288 : {
2289 0 : nEPSG = 4326;
2290 : }
2291 :
2292 : // ----------------------------------------------------------------------
2293 : // Match GCS's DATUM_NAME by using 'ApproxString' over Datum
2294 : // ----------------------------------------------------------------------
2295 :
2296 0 : if( nEPSG == 0 )
2297 : {
2298 : nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ),
2299 0 : "DATUM_NAME", pszDatum, CC_ApproxString, "COORD_REF_SYS_CODE" ) );
2300 : }
2301 :
2302 : // ----------------------------------------------------------------------
2303 : // Match GCS's COORD_REF_SYS_NAME by using 'ApproxString' over Datum
2304 : // ----------------------------------------------------------------------
2305 :
2306 0 : if( nEPSG == 0 )
2307 : {
2308 : nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ),
2309 0 : "COORD_REF_SYS_NAME", pszDatum, CC_ApproxString, "COORD_REF_SYS_CODE" ) );
2310 : }
2311 :
2312 0 : if( nEPSG != 0 )
2313 : {
2314 0 : oSRS.importFromEPSG( nEPSG );
2315 : }
2316 : else
2317 : {
2318 : // --------------------------------------------------
2319 : // Create GeogCS based on the georeference file info
2320 : // --------------------------------------------------
2321 :
2322 : oSRS.SetGeogCS( pszRefSystem,
2323 : pszDatum,
2324 : pszEllipsoid,
2325 : dfSemiMajor,
2326 0 : ( -1.0 /( dfSemiMinor / dfSemiMajor - 1.0 ) ) );
2327 : }
2328 :
2329 : // ----------------------------------------------------------------------
2330 : // Note: That will override EPSG info:
2331 : // ----------------------------------------------------------------------
2332 :
2333 0 : oSRS.SetTOWGS84( adfToWGS84[0], adfToWGS84[1], adfToWGS84[2] );
2334 : }
2335 :
2336 : // ----------------------------------------------------------------------
2337 : // If the georeference file tells that it is a non project system:
2338 : // ----------------------------------------------------------------------
2339 :
2340 0 : if( EQUAL( pszProjName, "none" ) )
2341 : {
2342 0 : oSRS.exportToWkt( pszProjString );
2343 :
2344 0 : CPLFree( pszGeorefName );
2345 0 : CPLFree( pszProjName );
2346 0 : CPLFree( pszDatum );
2347 0 : CPLFree( pszEllipsoid );
2348 :
2349 0 : return CE_None;
2350 : }
2351 :
2352 : // ----------------------------------------------------------------------
2353 : // Create Projection information based on georeference file info
2354 : // ----------------------------------------------------------------------
2355 :
2356 : // Idrisi user's Manual, Supported Projection:
2357 : //
2358 : // Mercator
2359 : // Transverse Mercator
2360 : // Gauss-Kruger
2361 : // Lambert Conformal Conic
2362 : // Plate Carree
2363 : // Hammer Aitoff
2364 : // Lambert North Polar Azimuthal Equal Area
2365 : // Lambert South Polar Azimuthal Equal Area
2366 : // Lambert Transverse Azimuthal Equal Area
2367 : // Lambert Oblique Polar Azimuthal Equal Area
2368 : // North Polar Stereographic
2369 : // South Polar Stereographic
2370 : // Transverse Stereographic
2371 : // Oblique Stereographic
2372 : // Albers Equal Area Conic
2373 : // Sinusoidal
2374 : //
2375 :
2376 0 : if( EQUAL( pszProjName, "Mercator" ) )
2377 : {
2378 0 : oSRS.SetMercator( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
2379 : }
2380 0 : else if EQUAL( pszProjName, "Transverse Mercator" )
2381 : {
2382 0 : oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
2383 : }
2384 0 : else if EQUALN( pszProjName, "Gauss-Kruger", 9 )
2385 : {
2386 0 : oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
2387 : }
2388 0 : else if( EQUAL( pszProjName, "Lambert Conformal Conic" ) )
2389 : {
2390 0 : oSRS.SetLCC( dfStdP1, dfStdP2, dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
2391 : }
2392 0 : else if( EQUALN( pszProjName, "Plate Carr" "\xE9" "e", 10 ) ) /* 'eacute' in ISO-8859-1 */
2393 : {
2394 0 : oSRS.SetEquirectangular( dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
2395 : }
2396 0 : else if( EQUAL( pszProjName, "Hammer Aitoff" ) )
2397 : {
2398 0 : oSRS.SetProjection( pszProjName );
2399 0 : oSRS.SetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
2400 0 : oSRS.SetProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
2401 0 : oSRS.SetProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
2402 0 : oSRS.SetProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
2403 : }
2404 0 : else if( EQUALN( pszProjName, "Lambert North Polar Azimuthal Equal Area", 15 ) ||
2405 : EQUALN( pszProjName, "Lambert South Polar Azimuthal Equal Area", 15 ) ||
2406 : EQUALN( pszProjName, "Lambert Transverse Azimuthal Equal Area", 15 ) ||
2407 : EQUALN( pszProjName, "Lambert Oblique Polar Azimuthal Equal Area", 15 ) )
2408 : {
2409 0 : oSRS.SetLAEA( dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
2410 : }
2411 0 : else if( EQUALN( pszProjName, "North Polar Stereographic", 15 ) ||
2412 : EQUALN( pszProjName, "South Polar Stereographic", 15 ) )
2413 : {
2414 0 : oSRS.SetPS( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
2415 : }
2416 0 : else if( EQUALN( pszProjName, "Transverse Stereographic", 15 ) )
2417 : {
2418 0 : oSRS.SetStereographic( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
2419 : }
2420 0 : else if( EQUALN( pszProjName, "Oblique Stereographic", 15 ) )
2421 : {
2422 0 : oSRS.SetOS( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
2423 : }
2424 0 : else if( EQUAL( pszProjName, "Alber's Equal Area Conic" ) ||
2425 : EQUAL( pszProjName, "Albers Equal Area Conic" ) )
2426 : {
2427 0 : oSRS.SetACEA( dfStdP1, dfStdP2, dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
2428 : }
2429 0 : else if( EQUAL( pszProjName, "Sinusoidal" ) )
2430 : {
2431 0 : oSRS.SetSinusoidal( dfCenterLong, dfFalseEasting, dfFalseNorthing );
2432 : }
2433 : else
2434 : {
2435 : CPLError( CE_Warning, CPLE_NotSupported,
2436 : "Projection not listed on Idrisi User's Manual( v.15.0/2005 ).\n\t"
2437 : "[\"%s\" in georeference file \"%s\"]",
2438 0 : pszProjName, pszFName );
2439 0 : oSRS.Clear();
2440 0 : oSRS.exportToWkt( pszProjString );
2441 :
2442 0 : CPLFree( pszGeorefName );
2443 0 : CPLFree( pszProjName );
2444 0 : CPLFree( pszDatum );
2445 0 : CPLFree( pszEllipsoid );
2446 :
2447 0 : return CE_Warning;
2448 : }
2449 :
2450 : // ----------------------------------------------------------------------
2451 : // Set the Linear Units
2452 : // ----------------------------------------------------------------------
2453 :
2454 0 : int nUnit = GetUnitIndex( pszRefUnits );
2455 0 : if( nUnit > -1 )
2456 : {
2457 0 : int nDeft = aoLinearUnitsConv[nUnit].nDefaultG;
2458 : oSRS.SetLinearUnits( aoLinearUnitsConv[nDeft].pszName,
2459 0 : aoLinearUnitsConv[nDeft].dfConv );
2460 : }
2461 : else
2462 : {
2463 0 : oSRS.SetLinearUnits( "unknown", 1.0 );
2464 : }
2465 :
2466 : // ----------------------------------------------------------------------
2467 : // Name ProjCS with the name on the georeference file
2468 : // ----------------------------------------------------------------------
2469 :
2470 0 : oSRS.SetProjCS( pszGeorefName );
2471 :
2472 0 : oSRS.exportToWkt( pszProjString );
2473 :
2474 0 : CPLFree( pszGeorefName );
2475 0 : CPLFree( pszProjName );
2476 0 : CPLFree( pszDatum );
2477 0 : CPLFree( pszEllipsoid );
2478 :
2479 0 : return CE_None;
2480 : }
2481 :
2482 : /************************************************************************/
2483 : /* Wkt2GeoReference() */
2484 : /************************************************************************/
2485 :
2486 : /***
2487 : * Converts OpenGIS WKT to Idrisi geographic reference information.
2488 : *
2489 : * That function will fill up the two parameters RefSystem and RefUnit
2490 : * that goes into the Idrisi metadata. But it could also create
2491 : * a companying georeference file to the output if necessary.
2492 : *
2493 : * First it will try to identify the ProjString as Local, WGS84 or
2494 : * one of the Idrisi name convention reference systems
2495 : * otherwise, if the projection system is supported by Idrisi,
2496 : * it will create a companying georeference files.
2497 : ***/
2498 :
2499 1 : CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
2500 : char **pszRefSystem,
2501 : char **pszRefUnit )
2502 : {
2503 : // -----------------------------------------------------
2504 : // Plane with default "Meters"
2505 : // -----------------------------------------------------
2506 :
2507 1 : if EQUAL( pszProjString, "" )
2508 : {
2509 0 : *pszRefSystem = CPLStrdup( rstPLANE );
2510 0 : *pszRefUnit = CPLStrdup( rstMETER );
2511 0 : return CE_None;
2512 : }
2513 :
2514 1 : OGRSpatialReference oSRS;
2515 1 : oSRS.importFromWkt( (char **) &pszProjString );
2516 :
2517 : // -----------------------------------------------------
2518 : // Local => Plane + Linear Unit
2519 : // -----------------------------------------------------
2520 :
2521 1 : if( oSRS.IsLocal() )
2522 : {
2523 0 : *pszRefSystem = CPLStrdup( rstPLANE );
2524 : *pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ),
2525 0 : CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
2526 0 : return CE_None;
2527 : }
2528 :
2529 : // -----------------------------------------------------
2530 : // Test to identify WGS84 => Latlong + Angular Unit
2531 : // -----------------------------------------------------
2532 :
2533 1 : if( oSRS.IsGeographic() )
2534 : {
2535 1 : char *pszSpheroid = CPLStrdup( oSRS.GetAttrValue( "SPHEROID" ) );
2536 1 : char *pszAuthName = CPLStrdup( oSRS.GetAuthorityName( "GEOGCS" ) );
2537 1 : char *pszDatum = CPLStrdup( oSRS.GetAttrValue( "DATUM" ) );
2538 1 : int nGCSCode = -1;
2539 1 : if EQUAL( pszAuthName, "EPSG" )
2540 : {
2541 1 : nGCSCode = atoi( oSRS.GetAuthorityCode( "GEOGCS" ) );
2542 : }
2543 1 : if( ( nGCSCode == 4326 ) ||(
2544 : ( EQUALN( pszSpheroid, "WGS", 3 ) ) &&( strstr( pszSpheroid, "84" ) ) &&
2545 : ( EQUALN( pszDatum, "WGS", 3 ) ) &&( strstr( pszDatum, "84" ) ) ) )
2546 : {
2547 1 : *pszRefSystem = CPLStrdup( rstLATLONG );
2548 1 : *pszRefUnit = CPLStrdup( rstDEGREE );
2549 :
2550 1 : CPLFree( pszSpheroid );
2551 1 : CPLFree( pszAuthName );
2552 1 : CPLFree( pszDatum );
2553 :
2554 1 : return CE_None;
2555 : }
2556 :
2557 0 : CPLFree( pszSpheroid );
2558 0 : CPLFree( pszAuthName );
2559 0 : CPLFree( pszDatum );
2560 : }
2561 :
2562 : // -----------------------------------------------------
2563 : // Prepare to match some projections
2564 : // -----------------------------------------------------
2565 :
2566 0 : const char *pszProjName = oSRS.GetAttrValue( "PROJECTION" );
2567 :
2568 0 : if( pszProjName == NULL )
2569 : {
2570 0 : pszProjName = "";
2571 : }
2572 :
2573 : // -----------------------------------------------------
2574 : // Check for UTM zones
2575 : // -----------------------------------------------------
2576 :
2577 0 : if( EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR ) )
2578 : {
2579 0 : int nZone = oSRS.GetUTMZone();
2580 :
2581 0 : if( ( nZone != 0 ) && ( EQUAL( oSRS.GetAttrValue( "DATUM" ), SRS_DN_WGS84 ) ) )
2582 : {
2583 0 : double dfNorth = oSRS.GetProjParm( SRS_PP_FALSE_NORTHING );
2584 0 : *pszRefSystem = CPLStrdup( CPLSPrintf( rstUTM, nZone,( dfNorth == 0.0 ? 'n' : 's' ) ) );
2585 0 : *pszRefUnit = CPLStrdup( rstMETER );
2586 0 : return CE_None;
2587 : }
2588 : }
2589 :
2590 : // -----------------------------------------------------
2591 : // Check for State Plane
2592 : // -----------------------------------------------------
2593 :
2594 : #ifndef GDAL_RST_PLUGIN
2595 :
2596 0 : if( EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP ) ||
2597 : EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR ) )
2598 : {
2599 : const char *pszPCSCode;
2600 0 : const char *pszID = CPLStrdup( oSRS.GetAuthorityCode( "PROJCS" ) );
2601 0 : if( strlen( pszID ) > 0 )
2602 : {
2603 : pszPCSCode = CPLStrdup( CSVGetField( CSVFilename( "stateplane.csv" ),
2604 0 : "EPSG_PCS_CODE", pszID, CC_Integer, "ID" ) );
2605 0 : if( strlen( pszPCSCode ) > 0 )
2606 : {
2607 0 : int nNADYear = 83;
2608 0 : int nZone = pszPCSCode[strlen( pszPCSCode ) - 1] - '0';
2609 0 : int nSPCode = atoi_nz( pszPCSCode );
2610 :
2611 0 : if( nZone == 0 )
2612 0 : nZone = 1;
2613 : else
2614 0 : nSPCode = nSPCode - nZone + 1;
2615 :
2616 0 : if( nSPCode > 10000 )
2617 : {
2618 0 : nNADYear = 27;
2619 0 : nSPCode -= 10000;
2620 : }
2621 0 : char *pszState = CPLStrdup( GetStateName( nSPCode ) );
2622 0 : if( ! EQUAL( pszState, "" ) )
2623 : {
2624 0 : *pszRefSystem = CPLStrdup( CPLSPrintf( rstSPC, nNADYear, pszState, nZone ) );
2625 : *pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ),
2626 0 : CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
2627 0 : return CE_None;
2628 : }
2629 : }
2630 : }
2631 : }
2632 :
2633 : #endif // GDAL_RST_PLUGIN
2634 :
2635 0 : const char *pszProjectionOut = NULL;
2636 :
2637 0 : if( oSRS.IsProjected() )
2638 : {
2639 : // ---------------------------------------------------------
2640 : // Check for supported projections
2641 : // ---------------------------------------------------------
2642 :
2643 0 : if EQUAL( pszProjName, SRS_PT_MERCATOR_1SP )
2644 : {
2645 0 : pszProjectionOut = "Mercator" ;
2646 : }
2647 0 : if EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR )
2648 : {
2649 0 : pszProjectionOut = "Transverse Mercator" ;
2650 : }
2651 0 : else if EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP )
2652 : {
2653 0 : pszProjectionOut = "Lambert Conformal Conic" ;
2654 : }
2655 0 : else if EQUAL( pszProjName, SRS_PT_EQUIRECTANGULAR )
2656 : {
2657 0 : pszProjectionOut = "Plate Carr" "\xE9" "e" ; /* 'eacute' in ISO-8859-1 */
2658 : }
2659 0 : else if EQUAL( pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA )
2660 : {
2661 0 : double dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
2662 0 : if( dfCenterLat == 0.0 )
2663 0 : pszProjectionOut = "Lambert Transverse Azimuthal Equal Area" ;
2664 0 : else if( fabs( dfCenterLat ) == 90.0 )
2665 0 : pszProjectionOut = "Lambert Oblique Polar Azimuthal Equal Area" ;
2666 0 : else if( dfCenterLat > 0.0 )
2667 0 : pszProjectionOut = "Lambert North Oblique Azimuthal Equal Area" ;
2668 : else
2669 0 : pszProjectionOut = "Lambert South Oblique Azimuthal Equal Area" ;
2670 : }
2671 0 : else if EQUAL( pszProjName, SRS_PT_POLAR_STEREOGRAPHIC )
2672 : {
2673 0 : if( oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL ) > 0 )
2674 0 : pszProjectionOut = "North Polar Stereographic" ;
2675 : else
2676 0 : pszProjectionOut = "South Polar Stereographic" ;
2677 : }
2678 0 : else if EQUAL( pszProjName, SRS_PT_STEREOGRAPHIC )
2679 : {
2680 0 : pszProjectionOut = "Transverse Stereographic" ;
2681 : }
2682 0 : else if EQUAL( pszProjName, SRS_PT_OBLIQUE_STEREOGRAPHIC )
2683 : {
2684 0 : pszProjectionOut = "Oblique Stereographic" ;
2685 : }
2686 0 : else if EQUAL( pszProjName, SRS_PT_SINUSOIDAL )
2687 : {
2688 0 : pszProjectionOut = "Sinusoidal" ;
2689 : }
2690 0 : else if EQUAL( pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA )
2691 : {
2692 0 : pszProjectionOut = "Alber's Equal Area Conic" ;
2693 : }
2694 :
2695 : // ---------------------------------------------------------
2696 : // Failure, Projection system not suppotted
2697 : // ---------------------------------------------------------
2698 :
2699 0 : if( pszProjectionOut == NULL )
2700 : {
2701 : CPLDebug( "RST",
2702 : "Not supported by RST driver: PROJECTION[\"%s\"]",
2703 0 : pszProjName );
2704 :
2705 0 : *pszRefSystem = CPLStrdup( rstPLANE );
2706 0 : *pszRefUnit = CPLStrdup( rstMETER );
2707 0 : return CE_Failure;
2708 : }
2709 : }
2710 : else
2711 : {
2712 0 : pszProjectionOut = "none" ;
2713 : }
2714 :
2715 : // ---------------------------------------------------------
2716 : // Prepare to write ref file
2717 : // ---------------------------------------------------------
2718 :
2719 0 : char *pszGeorefName = CPLStrdup( "Unknown" );
2720 0 : char *pszDatum = CPLStrdup( oSRS.GetAttrValue( "DATUM" ) );
2721 0 : char *pszEllipsoid = CPLStrdup( oSRS.GetAttrValue( "SPHEROID" ) );
2722 0 : double dfSemiMajor = oSRS.GetSemiMajor();
2723 0 : double dfSemiMinor = oSRS.GetSemiMinor();
2724 : double adfToWGS84[3];
2725 0 : oSRS.GetTOWGS84( adfToWGS84, 3 );
2726 :
2727 0 : double dfCenterLat = 0.0;
2728 0 : double dfCenterLong = 0.0;
2729 0 : double dfFalseNorthing = 0.0;
2730 0 : double dfFalseEasting = 0.0;
2731 0 : double dfScale = 1.0;
2732 0 : int nParameters = 0;
2733 0 : double dfStdP1 = 0.0;
2734 0 : double dfStdP2 = 0.0;
2735 0 : char *pszAngularUnit = CPLStrdup( oSRS.GetAttrValue( "GEOGCS|UNIT" ) );
2736 : char *pszLinearUnit;
2737 :
2738 0 : if( oSRS.IsProjected() )
2739 : {
2740 0 : CPLFree( pszGeorefName );
2741 0 : pszGeorefName = CPLStrdup( oSRS.GetAttrValue( "PROJCS" ) );
2742 0 : dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
2743 0 : dfCenterLong = oSRS.GetProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL );
2744 0 : dfFalseNorthing = oSRS.GetProjParm( SRS_PP_FALSE_NORTHING, 0.0, NULL );
2745 0 : dfFalseEasting = oSRS.GetProjParm( SRS_PP_FALSE_EASTING, 0.0, NULL );
2746 0 : dfScale = oSRS.GetProjParm( SRS_PP_SCALE_FACTOR, 0.0, NULL );
2747 0 : dfStdP1 = oSRS.GetProjParm( SRS_PP_STANDARD_PARALLEL_1, -0.1, NULL );
2748 0 : dfStdP2 = oSRS.GetProjParm( SRS_PP_STANDARD_PARALLEL_2, -0.1, NULL );
2749 0 : if( dfStdP1 != -0.1 )
2750 : {
2751 0 : nParameters = 1;
2752 0 : if( dfStdP2 != -0.1 )
2753 0 : nParameters = 2;
2754 : }
2755 : pszLinearUnit = GetUnitDefault( oSRS.GetAttrValue( "PROJCS|UNIT" ),
2756 0 : CPLSPrintf( "%f", oSRS.GetLinearUnits() ) ) ;
2757 : }
2758 : else
2759 : {
2760 0 : pszLinearUnit = GetUnitDefault( pszAngularUnit );
2761 : }
2762 :
2763 : // ---------------------------------------------------------
2764 : // Create a compaining georeference file for this dataset
2765 : // ---------------------------------------------------------
2766 :
2767 0 : char **papszRef = NULL;
2768 0 : papszRef = CSLAddNameValue( papszRef, refREF_SYSTEM, pszGeorefName );
2769 0 : papszRef = CSLAddNameValue( papszRef, refPROJECTION, pszProjectionOut );
2770 0 : papszRef = CSLAddNameValue( papszRef, refDATUM, pszDatum );
2771 : papszRef = CSLAddNameValue( papszRef, refDELTA_WGS84, CPLSPrintf( "%.3g %.3g %.3g",
2772 0 : adfToWGS84[0], adfToWGS84[1], adfToWGS84[2] ) );
2773 0 : papszRef = CSLAddNameValue( papszRef, refELLIPSOID, pszEllipsoid );
2774 0 : papszRef = CSLAddNameValue( papszRef, refMAJOR_SAX, CPLSPrintf( "%.3f", dfSemiMajor ) );
2775 0 : papszRef = CSLAddNameValue( papszRef, refMINOR_SAX, CPLSPrintf( "%.3f", dfSemiMinor ) );
2776 0 : papszRef = CSLAddNameValue( papszRef, refORIGIN_LONG, CPLSPrintf( "%.9g", dfCenterLong ) );
2777 0 : papszRef = CSLAddNameValue( papszRef, refORIGIN_LAT, CPLSPrintf( "%.9g", dfCenterLat ) );
2778 0 : papszRef = CSLAddNameValue( papszRef, refORIGIN_X, CPLSPrintf( "%.9g", dfFalseEasting ) );
2779 0 : papszRef = CSLAddNameValue( papszRef, refORIGIN_Y, CPLSPrintf( "%.9g", dfFalseNorthing ) );
2780 0 : papszRef = CSLAddNameValue( papszRef, refSCALE_FAC, CPLSPrintf( "%.9g", dfScale ) );
2781 0 : papszRef = CSLAddNameValue( papszRef, refUNITS, pszLinearUnit );
2782 0 : papszRef = CSLAddNameValue( papszRef, refPARAMETERS, CPLSPrintf( "%1d", nParameters ) );
2783 0 : if( nParameters > 0 )
2784 0 : papszRef = CSLAddNameValue( papszRef, refSTANDL_1, CPLSPrintf( "%.9g", dfStdP1 ) );
2785 0 : if( nParameters > 1 )
2786 0 : papszRef = CSLAddNameValue( papszRef, refSTANDL_2, CPLSPrintf( "%.9g", dfStdP2 ) );
2787 0 : CSLSetNameValueSeparator( papszRef, ": " );
2788 0 : SaveAsCRLF( papszRef, CPLResetExtension( pszFilename, extREF ) );
2789 0 : CSLDestroy( papszRef );
2790 :
2791 0 : *pszRefSystem = CPLStrdup( CPLGetBasename( pszFilename ) );
2792 0 : *pszRefUnit = CPLStrdup( pszLinearUnit );
2793 :
2794 0 : CPLFree( pszGeorefName );
2795 0 : CPLFree( pszDatum );
2796 0 : CPLFree( pszEllipsoid );
2797 0 : CPLFree( pszLinearUnit );
2798 0 : CPLFree( pszAngularUnit );
2799 :
2800 0 : return CE_None;
2801 : }
2802 :
2803 : /************************************************************************/
2804 : /* FileExists() */
2805 : /************************************************************************/
2806 :
2807 18 : bool FileExists( const char *pszPath )
2808 : {
2809 : VSIStatBuf sStat;
2810 :
2811 18 : return (bool) ( CPLStat( pszPath, &sStat ) == 0 );
2812 : }
2813 :
2814 : /************************************************************************/
2815 : /* GetStateCode() */
2816 : /************************************************************************/
2817 :
2818 0 : int GetStateCode( const char *pszState )
2819 : {
2820 : unsigned int i;
2821 :
2822 0 : for( i = 0; i < US_STATE_COUNT; i++ )
2823 : {
2824 0 : if EQUAL( pszState, aoUSStateTable[i].pszName )
2825 : {
2826 0 : return aoUSStateTable[i].nCode;
2827 : }
2828 : }
2829 0 : return -1;
2830 : }
2831 :
2832 : /************************************************************************/
2833 : /* GetStateCode() */
2834 : /************************************************************************/
2835 :
2836 0 : const char *GetStateName( int nCode )
2837 : {
2838 : unsigned int i;
2839 :
2840 0 : for( i = 0; i < US_STATE_COUNT; i++ )
2841 : {
2842 0 : if( nCode == aoUSStateTable[i].nCode )
2843 : {
2844 0 : return aoUSStateTable[i].pszName;
2845 : }
2846 : }
2847 0 : return NULL;
2848 : }
2849 :
2850 : /************************************************************************/
2851 : /* GetUnitIndex() */
2852 : /************************************************************************/
2853 :
2854 0 : int GetUnitIndex( const char *pszUnitName )
2855 : {
2856 : int i;
2857 :
2858 0 : for( i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
2859 : {
2860 0 : if EQUAL( pszUnitName, aoLinearUnitsConv[i].pszName )
2861 : {
2862 0 : return i;
2863 : }
2864 : }
2865 0 : return -1;
2866 : }
2867 :
2868 : /************************************************************************/
2869 : /* GetToMeterIndex() */
2870 : /************************************************************************/
2871 :
2872 0 : int GetToMeterIndex( const char *pszToMeter )
2873 : {
2874 0 : double dfToMeter = atof_nz(pszToMeter);
2875 :
2876 0 : if( dfToMeter != 0.0 )
2877 : {
2878 : int i;
2879 :
2880 0 : for( i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
2881 : {
2882 0 : if ( ABS( aoLinearUnitsConv[i].dfConv - dfToMeter ) < 0.00001 )
2883 : {
2884 0 : return i;
2885 : }
2886 : }
2887 : }
2888 :
2889 0 : return -1;
2890 : }
2891 :
2892 : /************************************************************************/
2893 : /* GetUnitDefault() */
2894 : /************************************************************************/
2895 :
2896 0 : char *GetUnitDefault( const char *pszUnitName, const char *pszToMeter )
2897 : {
2898 0 : int nIndex = GetUnitIndex( pszUnitName );
2899 :
2900 0 : if( nIndex == -1 && pszToMeter != NULL )
2901 : {
2902 0 : nIndex = GetToMeterIndex( pszToMeter );
2903 : }
2904 :
2905 0 : if( nIndex == -1 )
2906 : {
2907 0 : return CPLStrdup( "Unknown" );
2908 : }
2909 :
2910 0 : return CPLStrdup( aoLinearUnitsConv[aoLinearUnitsConv[nIndex].nDefaultI].pszName );
2911 : }
2912 :
2913 : /************************************************************************/
2914 : /* CSLSaveCRLF() */
2915 : /************************************************************************/
2916 :
2917 : /***
2918 : * Write a stringlist to a CR + LF terminated text file.
2919 : *
2920 : * Returns the number of lines written, or 0 if the file could not
2921 : * be written.
2922 : */
2923 :
2924 12 : int SaveAsCRLF(char **papszStrList, const char *pszFname)
2925 : {
2926 : FILE *fp;
2927 12 : int nLines = 0;
2928 :
2929 12 : if (papszStrList)
2930 : {
2931 12 : if ((fp = VSIFOpenL(pszFname, "wt")) != NULL)
2932 : {
2933 336 : while(*papszStrList != NULL)
2934 : {
2935 312 : if( VSIFPrintfL( fp, "%s\r\n", *papszStrList ) < 1 )
2936 : {
2937 : CPLError( CE_Failure, CPLE_FileIO,
2938 : "CSLSaveCRLF(\"%s\") failed: unable to write to output file.",
2939 0 : pszFname );
2940 0 : break;
2941 : }
2942 :
2943 312 : nLines++;
2944 312 : papszStrList++;
2945 : }
2946 :
2947 12 : VSIFCloseL(fp);
2948 : }
2949 : else
2950 : {
2951 : CPLError( CE_Failure, CPLE_OpenFailed,
2952 : "CSLSaveCRLF(\"%s\") failed: unable to open output file.",
2953 0 : pszFname );
2954 : }
2955 : }
2956 :
2957 12 : return nLines;
2958 : }
2959 :
2960 : /************************************************************************/
2961 : /* GDALRegister_IDRISI() */
2962 : /************************************************************************/
2963 338 : void GDALRegister_IDRISI()
2964 : {
2965 : GDALDriver *poDriver;
2966 :
2967 338 : if( GDALGetDriverByName( "RST" ) == NULL )
2968 : {
2969 336 : poDriver = new GDALDriver();
2970 :
2971 336 : poDriver->SetDescription( "RST" );
2972 336 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, rstVERSION );
2973 336 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_Idrisi.html" );
2974 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, extRST );
2975 336 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 Float32" );
2976 336 : poDriver->pfnOpen = IdrisiDataset::Open;
2977 336 : poDriver->pfnCreate = IdrisiDataset::Create;
2978 336 : poDriver->pfnCreateCopy = IdrisiDataset::CreateCopy;
2979 :
2980 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
2981 : }
2982 338 : }
2983 :
|