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