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