1 : /******************************************************************************
2 : * $Id: hfadataset.cpp 22909 2011-08-08 19:03:36Z rouault $
3 : *
4 : * Name: hfadataset.cpp
5 : * Project: Erdas Imagine Driver
6 : * Purpose: Main driver for Erdas Imagine format.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Frank Warmerdam
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "gdal_pam.h"
32 : #include "gdal_rat.h"
33 : #include "hfa_p.h"
34 : #include "ogr_spatialref.h"
35 :
36 : CPL_CVSID("$Id: hfadataset.cpp 22909 2011-08-08 19:03:36Z rouault $");
37 :
38 : CPL_C_START
39 : void GDALRegister_HFA(void);
40 : CPL_C_END
41 :
42 : #ifndef PI
43 : # define PI 3.14159265358979323846
44 : #endif
45 :
46 : #ifndef R2D
47 : # define R2D (180/PI)
48 : #endif
49 : #ifndef D2R
50 : # define D2R (PI/180)
51 : #endif
52 :
53 : int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA);
54 : void ClearSR(HFAHandle hHFA);
55 :
56 : static const char *apszDatumMap[] = {
57 : /* Imagine name, WKT name */
58 : "NAD27", "North_American_Datum_1927",
59 : "NAD83", "North_American_Datum_1983",
60 : "WGS 84", "WGS_1984",
61 : "WGS 1972", "WGS_1972",
62 : "GDA94", "Geocentric_Datum_of_Australia_1994",
63 : NULL, NULL
64 : };
65 :
66 : static const char *apszUnitMap[] = {
67 : "meters", "1.0",
68 : "meter", "1.0",
69 : "m", "1.0",
70 : "centimeters", "0.01",
71 : "centimeter", "0.01",
72 : "cm", "0.01",
73 : "millimeters", "0.001",
74 : "millimeter", "0.001",
75 : "mm", "0.001",
76 : "kilometers", "1000.0",
77 : "kilometer", "1000.0",
78 : "km", "1000.0",
79 : "us_survey_feet", "0.3048006096012192",
80 : "us_survey_foot", "0.3048006096012192",
81 : "feet", "0.3048006096012192",
82 : "foot", "0.3048006096012192",
83 : "ft", "0.3048006096012192",
84 : "international_feet", "0.3048",
85 : "international_foot", "0.3048",
86 : "inches", "0.0254000508001",
87 : "inch", "0.0254000508001",
88 : "in", "0.0254000508001",
89 : "yards", "0.9144",
90 : "yard", "0.9144",
91 : "yd", "0.9144",
92 : "miles", "1304.544",
93 : "mile", "1304.544",
94 : "mi", "1304.544",
95 : "modified_american_feet", "0.3048122530",
96 : "modified_american_foot", "0.3048122530",
97 : "clarke_feet", "0.3047972651",
98 : "clarke_foot", "0.3047972651",
99 : "indian_feet", "0.3047995142",
100 : "indian_foot", "0.3047995142",
101 : NULL, NULL
102 : };
103 :
104 :
105 : /* ==================================================================== */
106 : /* Table relating USGS and ESRI state plane zones. */
107 : /* ==================================================================== */
108 : static const int anUsgsEsriZones[] =
109 : {
110 : 101, 3101,
111 : 102, 3126,
112 : 201, 3151,
113 : 202, 3176,
114 : 203, 3201,
115 : 301, 3226,
116 : 302, 3251,
117 : 401, 3276,
118 : 402, 3301,
119 : 403, 3326,
120 : 404, 3351,
121 : 405, 3376,
122 : 406, 3401,
123 : 407, 3426,
124 : 501, 3451,
125 : 502, 3476,
126 : 503, 3501,
127 : 600, 3526,
128 : 700, 3551,
129 : 901, 3601,
130 : 902, 3626,
131 : 903, 3576,
132 : 1001, 3651,
133 : 1002, 3676,
134 : 1101, 3701,
135 : 1102, 3726,
136 : 1103, 3751,
137 : 1201, 3776,
138 : 1202, 3801,
139 : 1301, 3826,
140 : 1302, 3851,
141 : 1401, 3876,
142 : 1402, 3901,
143 : 1501, 3926,
144 : 1502, 3951,
145 : 1601, 3976,
146 : 1602, 4001,
147 : 1701, 4026,
148 : 1702, 4051,
149 : 1703, 6426,
150 : 1801, 4076,
151 : 1802, 4101,
152 : 1900, 4126,
153 : 2001, 4151,
154 : 2002, 4176,
155 : 2101, 4201,
156 : 2102, 4226,
157 : 2103, 4251,
158 : 2111, 6351,
159 : 2112, 6376,
160 : 2113, 6401,
161 : 2201, 4276,
162 : 2202, 4301,
163 : 2203, 4326,
164 : 2301, 4351,
165 : 2302, 4376,
166 : 2401, 4401,
167 : 2402, 4426,
168 : 2403, 4451,
169 : 2500, 0,
170 : 2501, 4476,
171 : 2502, 4501,
172 : 2503, 4526,
173 : 2600, 0,
174 : 2601, 4551,
175 : 2602, 4576,
176 : 2701, 4601,
177 : 2702, 4626,
178 : 2703, 4651,
179 : 2800, 4676,
180 : 2900, 4701,
181 : 3001, 4726,
182 : 3002, 4751,
183 : 3003, 4776,
184 : 3101, 4801,
185 : 3102, 4826,
186 : 3103, 4851,
187 : 3104, 4876,
188 : 3200, 4901,
189 : 3301, 4926,
190 : 3302, 4951,
191 : 3401, 4976,
192 : 3402, 5001,
193 : 3501, 5026,
194 : 3502, 5051,
195 : 3601, 5076,
196 : 3602, 5101,
197 : 3701, 5126,
198 : 3702, 5151,
199 : 3800, 5176,
200 : 3900, 0,
201 : 3901, 5201,
202 : 3902, 5226,
203 : 4001, 5251,
204 : 4002, 5276,
205 : 4100, 5301,
206 : 4201, 5326,
207 : 4202, 5351,
208 : 4203, 5376,
209 : 4204, 5401,
210 : 4205, 5426,
211 : 4301, 5451,
212 : 4302, 5476,
213 : 4303, 5501,
214 : 4400, 5526,
215 : 4501, 5551,
216 : 4502, 5576,
217 : 4601, 5601,
218 : 4602, 5626,
219 : 4701, 5651,
220 : 4702, 5676,
221 : 4801, 5701,
222 : 4802, 5726,
223 : 4803, 5751,
224 : 4901, 5776,
225 : 4902, 5801,
226 : 4903, 5826,
227 : 4904, 5851,
228 : 5001, 6101,
229 : 5002, 6126,
230 : 5003, 6151,
231 : 5004, 6176,
232 : 5005, 6201,
233 : 5006, 6226,
234 : 5007, 6251,
235 : 5008, 6276,
236 : 5009, 6301,
237 : 5010, 6326,
238 : 5101, 5876,
239 : 5102, 5901,
240 : 5103, 5926,
241 : 5104, 5951,
242 : 5105, 5976,
243 : 5201, 6001,
244 : 5200, 6026,
245 : 5200, 6076,
246 : 5201, 6051,
247 : 5202, 6051,
248 : 5300, 0,
249 : 5400, 0
250 : };
251 :
252 :
253 : /************************************************************************/
254 : /* ==================================================================== */
255 : /* HFADataset */
256 : /* ==================================================================== */
257 : /************************************************************************/
258 :
259 : class HFARasterBand;
260 :
261 : class CPL_DLL HFADataset : public GDALPamDataset
262 : {
263 : friend class HFARasterBand;
264 :
265 : HFAHandle hHFA;
266 :
267 : int bMetadataDirty;
268 :
269 : int bGeoDirty;
270 : double adfGeoTransform[6];
271 : char *pszProjection;
272 :
273 : int bIgnoreUTM;
274 :
275 : CPLErr ReadProjection();
276 : CPLErr WriteProjection();
277 : int bForceToPEString;
278 :
279 : int nGCPCount;
280 : GDAL_GCP asGCPList[36];
281 :
282 : void UseXFormStack( int nStepCount,
283 : Efga_Polynomial *pasPolyListForward,
284 : Efga_Polynomial *pasPolyListReverse );
285 :
286 : protected:
287 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
288 : void *, int, int, GDALDataType,
289 : int, int *, int, int, int );
290 :
291 : public:
292 : HFADataset();
293 : ~HFADataset();
294 :
295 : static int Identify( GDALOpenInfo * );
296 : static CPLErr Rename( const char *pszNewName, const char *pszOldName);
297 : static CPLErr CopyFiles( const char *pszNewName, const char *pszOldName);
298 : static GDALDataset *Open( GDALOpenInfo * );
299 : static GDALDataset *Create( const char * pszFilename,
300 : int nXSize, int nYSize, int nBands,
301 : GDALDataType eType, char ** papszParmList );
302 : static GDALDataset *CreateCopy( const char * pszFilename,
303 : GDALDataset *poSrcDS,
304 : int bStrict, char ** papszOptions,
305 : GDALProgressFunc pfnProgress,
306 : void * pProgressData );
307 : static CPLErr Delete( const char *pszFilename );
308 :
309 : virtual char **GetFileList(void);
310 :
311 : virtual const char *GetProjectionRef(void);
312 : virtual CPLErr SetProjection( const char * );
313 :
314 : virtual CPLErr GetGeoTransform( double * );
315 : virtual CPLErr SetGeoTransform( double * );
316 :
317 : virtual int GetGCPCount();
318 : virtual const char *GetGCPProjection();
319 : virtual const GDAL_GCP *GetGCPs();
320 :
321 : virtual CPLErr SetMetadata( char **, const char * = "" );
322 : virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
323 :
324 : virtual void FlushCache( void );
325 : virtual CPLErr IBuildOverviews( const char *pszResampling,
326 : int nOverviews, int *panOverviewList,
327 : int nListBands, int *panBandList,
328 : GDALProgressFunc pfnProgress,
329 : void * pProgressData );
330 : };
331 :
332 : /************************************************************************/
333 : /* ==================================================================== */
334 : /* HFARasterBand */
335 : /* ==================================================================== */
336 : /************************************************************************/
337 :
338 : class HFARasterBand : public GDALPamRasterBand
339 : {
340 : friend class HFADataset;
341 :
342 : GDALColorTable *poCT;
343 :
344 : int nHFADataType;
345 :
346 : int nOverviews;
347 : int nThisOverview;
348 : HFARasterBand **papoOverviewBands;
349 :
350 : CPLErr CleanOverviews();
351 :
352 : HFAHandle hHFA;
353 :
354 : int bMetadataDirty;
355 :
356 : GDALRasterAttributeTable *poDefaultRAT;
357 :
358 : void ReadAuxMetadata();
359 : void ReadHistogramMetadata();
360 : void EstablishOverviews();
361 : CPLErr WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT );
362 :
363 :
364 : GDALRasterAttributeTable* ReadNamedRAT( const char *pszName );
365 :
366 : public:
367 :
368 : HFARasterBand( HFADataset *, int, int );
369 : virtual ~HFARasterBand();
370 :
371 : virtual CPLErr IReadBlock( int, int, void * );
372 : virtual CPLErr IWriteBlock( int, int, void * );
373 :
374 : virtual const char *GetDescription() const;
375 : virtual void SetDescription( const char * );
376 :
377 : virtual GDALColorInterp GetColorInterpretation();
378 : virtual GDALColorTable *GetColorTable();
379 : virtual CPLErr SetColorTable( GDALColorTable * );
380 : virtual int GetOverviewCount();
381 : virtual GDALRasterBand *GetOverview( int );
382 :
383 : virtual double GetMinimum( int *pbSuccess = NULL );
384 : virtual double GetMaximum(int *pbSuccess = NULL );
385 : virtual double GetNoDataValue( int *pbSuccess = NULL );
386 : virtual CPLErr SetNoDataValue( double dfValue );
387 :
388 : virtual CPLErr SetMetadata( char **, const char * = "" );
389 : virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
390 : virtual CPLErr BuildOverviews( const char *, int, int *,
391 : GDALProgressFunc, void * );
392 :
393 : virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
394 : int *pnBuckets, int ** ppanHistogram,
395 : int bForce,
396 : GDALProgressFunc, void *pProgressData);
397 :
398 : virtual const GDALRasterAttributeTable *GetDefaultRAT();
399 : virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
400 : };
401 :
402 : /************************************************************************/
403 : /* HFARasterBand() */
404 : /************************************************************************/
405 :
406 485 : HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
407 :
408 : {
409 : int nCompression;
410 :
411 485 : if( iOverview == -1 )
412 450 : this->poDS = poDS;
413 : else
414 35 : this->poDS = NULL;
415 :
416 485 : this->hHFA = poDS->hHFA;
417 485 : this->nBand = nBand;
418 485 : this->poCT = NULL;
419 485 : this->nThisOverview = iOverview;
420 485 : this->papoOverviewBands = NULL;
421 485 : this->bMetadataDirty = FALSE;
422 485 : this->poDefaultRAT = NULL;
423 485 : this->nOverviews = -1;
424 :
425 : HFAGetBandInfo( hHFA, nBand, &nHFADataType,
426 485 : &nBlockXSize, &nBlockYSize, &nCompression );
427 :
428 : /* -------------------------------------------------------------------- */
429 : /* If this is an overview, we need to fetch the actual size, */
430 : /* and block size. */
431 : /* -------------------------------------------------------------------- */
432 485 : if( iOverview > -1 )
433 : {
434 : int nHFADataTypeO;
435 :
436 35 : nOverviews = 0;
437 : HFAGetOverviewInfo( hHFA, nBand, iOverview,
438 : &nRasterXSize, &nRasterYSize,
439 35 : &nBlockXSize, &nBlockYSize, &nHFADataTypeO );
440 :
441 : /* -------------------------------------------------------------------- */
442 : /* If we are an 8bit overview of a 1bit layer, we need to mark */
443 : /* ourselves as being "resample: average_bit2grayscale". */
444 : /* -------------------------------------------------------------------- */
445 35 : if( nHFADataType == EPT_u1 && nHFADataTypeO == EPT_u8 )
446 : {
447 : GDALMajorObject::SetMetadataItem( "RESAMPLING",
448 5 : "AVERAGE_BIT2GRAYSCALE" );
449 5 : GDALMajorObject::SetMetadataItem( "NBITS", "8" );
450 5 : nHFADataType = nHFADataTypeO;
451 : }
452 : }
453 :
454 : /* -------------------------------------------------------------------- */
455 : /* Set some other information. */
456 : /* -------------------------------------------------------------------- */
457 485 : if( nCompression != 0 )
458 : GDALMajorObject::SetMetadataItem( "COMPRESSION", "RLE",
459 63 : "IMAGE_STRUCTURE" );
460 :
461 485 : switch( nHFADataType )
462 : {
463 : case EPT_u1:
464 : case EPT_u2:
465 : case EPT_u4:
466 : case EPT_u8:
467 : case EPT_s8:
468 272 : eDataType = GDT_Byte;
469 272 : break;
470 :
471 : case EPT_u16:
472 33 : eDataType = GDT_UInt16;
473 33 : break;
474 :
475 : case EPT_s16:
476 22 : eDataType = GDT_Int16;
477 22 : break;
478 :
479 : case EPT_u32:
480 22 : eDataType = GDT_UInt32;
481 22 : break;
482 :
483 : case EPT_s32:
484 35 : eDataType = GDT_Int32;
485 35 : break;
486 :
487 : case EPT_f32:
488 28 : eDataType = GDT_Float32;
489 28 : break;
490 :
491 : case EPT_f64:
492 31 : eDataType = GDT_Float64;
493 31 : break;
494 :
495 : case EPT_c64:
496 21 : eDataType = GDT_CFloat32;
497 21 : break;
498 :
499 : case EPT_c128:
500 21 : eDataType = GDT_CFloat64;
501 21 : break;
502 :
503 : default:
504 0 : eDataType = GDT_Byte;
505 : /* notdef: this should really report an error, but this isn't
506 : so easy from within constructors. */
507 : CPLDebug( "GDAL", "Unsupported pixel type in HFARasterBand: %d.",
508 0 : (int) nHFADataType );
509 : break;
510 : }
511 :
512 485 : if( HFAGetDataTypeBits( nHFADataType ) < 8 )
513 : {
514 : GDALMajorObject::SetMetadataItem(
515 : "NBITS",
516 10 : CPLString().Printf( "%d", HFAGetDataTypeBits( nHFADataType ) ), "IMAGE_STRUCTURE" );
517 : }
518 :
519 485 : if( nHFADataType == EPT_s8 )
520 : {
521 : GDALMajorObject::SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
522 2 : "IMAGE_STRUCTURE" );
523 : }
524 :
525 : /* -------------------------------------------------------------------- */
526 : /* Collect color table if present. */
527 : /* -------------------------------------------------------------------- */
528 : double *padfRed, *padfGreen, *padfBlue, *padfAlpha, *padfBins;
529 : int nColors;
530 :
531 485 : if( iOverview == -1
532 : && HFAGetPCT( hHFA, nBand, &nColors,
533 : &padfRed, &padfGreen, &padfBlue, &padfAlpha,
534 : &padfBins ) == CE_None
535 : && nColors > 0 )
536 : {
537 7 : poCT = new GDALColorTable();
538 713 : for( int iColor = 0; iColor < nColors; iColor++ )
539 : {
540 : GDALColorEntry sEntry;
541 :
542 : // The following mapping assigns "equal sized" section of
543 : // the [0...1] range to each possible output value and avoid
544 : // rounding issues for the "normal" values generated using n/255.
545 : // See bug #1732 for some discussion.
546 706 : sEntry.c1 = MIN(255,(short) (padfRed[iColor] * 256));
547 706 : sEntry.c2 = MIN(255,(short) (padfGreen[iColor] * 256));
548 706 : sEntry.c3 = MIN(255,(short) (padfBlue[iColor] * 256));
549 706 : sEntry.c4 = MIN(255,(short) (padfAlpha[iColor] * 256));
550 :
551 706 : if( padfBins != NULL )
552 300 : poCT->SetColorEntry( (int) padfBins[iColor], &sEntry );
553 : else
554 406 : poCT->SetColorEntry( iColor, &sEntry );
555 : }
556 : }
557 :
558 485 : poDefaultRAT = ReadNamedRAT( "Descriptor_Table" );
559 485 : }
560 :
561 : /************************************************************************/
562 : /* ~HFARasterBand() */
563 : /************************************************************************/
564 :
565 485 : HFARasterBand::~HFARasterBand()
566 :
567 : {
568 485 : FlushCache();
569 :
570 519 : for( int iOvIndex = 0; iOvIndex < nOverviews; iOvIndex++ )
571 : {
572 34 : delete papoOverviewBands[iOvIndex];
573 : }
574 485 : CPLFree( papoOverviewBands );
575 :
576 485 : if( poCT != NULL )
577 6 : delete poCT;
578 :
579 485 : if( poDefaultRAT )
580 54 : delete poDefaultRAT;
581 485 : }
582 :
583 : /************************************************************************/
584 : /* ReadAuxMetadata() */
585 : /************************************************************************/
586 :
587 450 : void HFARasterBand::ReadAuxMetadata()
588 :
589 : {
590 : int i;
591 450 : HFABand *poBand = hHFA->papoBand[nBand-1];
592 :
593 : // only load metadata for full resolution layer.
594 450 : if( nThisOverview != -1 )
595 0 : return;
596 :
597 450 : const char ** pszAuxMetaData = GetHFAAuxMetaDataList();
598 6300 : for( i = 0; pszAuxMetaData[i] != NULL; i += 4 )
599 : {
600 : HFAEntry *poEntry;
601 :
602 5850 : if( strlen(pszAuxMetaData[i]) > 0 )
603 5400 : poEntry = poBand->poNode->GetNamedChild( pszAuxMetaData[i] );
604 : else
605 450 : poEntry = poBand->poNode;
606 :
607 5850 : const char *pszFieldName = pszAuxMetaData[i+1] + 1;
608 5850 : CPLErr eErr = CE_None;
609 :
610 5850 : if( poEntry == NULL )
611 4869 : continue;
612 :
613 981 : switch( pszAuxMetaData[i+1][0] )
614 : {
615 : case 'd':
616 : {
617 : int nCount, iValue;
618 : double dfValue;
619 399 : CPLString osValueList;
620 :
621 399 : nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
622 399 : for( iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
623 : {
624 383 : CPLString osSubFieldName;
625 383 : osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
626 383 : dfValue = poEntry->GetDoubleField( osSubFieldName, &eErr );
627 383 : if( eErr != CE_None )
628 : break;
629 :
630 : char szValueAsString[100];
631 363 : sprintf( szValueAsString, "%.14g", dfValue );
632 :
633 363 : if( iValue > 0 )
634 2 : osValueList += ",";
635 363 : osValueList += szValueAsString;
636 : }
637 399 : if( eErr == CE_None )
638 379 : SetMetadataItem( pszAuxMetaData[i+2], osValueList );
639 : }
640 399 : break;
641 : case 'i':
642 : case 'l':
643 : {
644 : int nValue, nCount, iValue;
645 132 : CPLString osValueList;
646 :
647 132 : nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
648 132 : for( iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
649 : {
650 132 : CPLString osSubFieldName;
651 132 : osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
652 132 : nValue = poEntry->GetIntField( osSubFieldName, &eErr );
653 132 : if( eErr != CE_None )
654 : break;
655 :
656 : char szValueAsString[100];
657 122 : sprintf( szValueAsString, "%d", nValue );
658 :
659 122 : if( iValue > 0 )
660 0 : osValueList += ",";
661 122 : osValueList += szValueAsString;
662 : }
663 132 : if( eErr == CE_None )
664 122 : SetMetadataItem( pszAuxMetaData[i+2], osValueList );
665 : }
666 132 : break;
667 : case 's':
668 : case 'e':
669 : {
670 : const char *pszValue;
671 450 : pszValue = poEntry->GetStringField( pszFieldName, &eErr );
672 450 : if( eErr == CE_None )
673 450 : SetMetadataItem( pszAuxMetaData[i+2], pszValue );
674 : }
675 450 : break;
676 : default:
677 0 : CPLAssert( FALSE );
678 : }
679 : }
680 : }
681 :
682 : /************************************************************************/
683 : /* ReadHistogramMetadata() */
684 : /************************************************************************/
685 :
686 450 : void HFARasterBand::ReadHistogramMetadata()
687 :
688 : {
689 : int i;
690 450 : HFABand *poBand = hHFA->papoBand[nBand-1];
691 :
692 : // only load metadata for full resolution layer.
693 450 : if( nThisOverview != -1 )
694 0 : return;
695 :
696 : HFAEntry *poEntry =
697 450 : poBand->poNode->GetNamedChild( "Descriptor_Table.Histogram" );
698 450 : if ( poEntry == NULL )
699 404 : return;
700 :
701 46 : int nNumBins = poEntry->GetIntField( "numRows" );
702 46 : if (nNumBins < 0)
703 0 : return;
704 :
705 : /* -------------------------------------------------------------------- */
706 : /* Fetch the histogram values. */
707 : /* -------------------------------------------------------------------- */
708 :
709 46 : int nOffset = poEntry->GetIntField( "columnDataPtr" );
710 46 : const char * pszType = poEntry->GetStringField( "dataType" );
711 46 : int nBinSize = 4;
712 :
713 46 : if( pszType != NULL && EQUALN( "real", pszType, 4 ) )
714 36 : nBinSize = 8;
715 :
716 46 : int *panHistValues = (int *) VSIMalloc2(sizeof(int), nNumBins);
717 46 : GByte *pabyWorkBuf = (GByte *) VSIMalloc2(nBinSize, nNumBins);
718 :
719 46 : if (panHistValues == NULL || pabyWorkBuf == NULL)
720 : {
721 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory");
722 0 : VSIFree(panHistValues);
723 0 : VSIFree(pabyWorkBuf);
724 0 : return;
725 : }
726 :
727 46 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
728 :
729 46 : if( (int)VSIFReadL( pabyWorkBuf, nBinSize, nNumBins, hHFA->fp ) != nNumBins)
730 : {
731 : CPLError( CE_Failure, CPLE_FileIO,
732 0 : "Cannot read histogram values." );
733 0 : CPLFree( panHistValues );
734 0 : CPLFree( pabyWorkBuf );
735 0 : return;
736 : }
737 :
738 : // Swap into local order.
739 46 : for( i = 0; i < nNumBins; i++ )
740 : HFAStandard( nBinSize, pabyWorkBuf + i*nBinSize );
741 :
742 46 : if( nBinSize == 8 ) // source is doubles
743 : {
744 6744 : for( i = 0; i < nNumBins; i++ )
745 6708 : panHistValues[i] = (int) ((double *) pabyWorkBuf)[i];
746 : }
747 : else // source is 32bit integers
748 : {
749 10 : memcpy( panHistValues, pabyWorkBuf, 4 * nNumBins );
750 : }
751 :
752 46 : CPLFree( pabyWorkBuf );
753 46 : pabyWorkBuf = NULL;
754 :
755 : /* -------------------------------------------------------------------- */
756 : /* Do we have unique values for the bins? */
757 : /* -------------------------------------------------------------------- */
758 46 : double *padfBinValues = NULL;
759 46 : HFAEntry *poBinEntry = poBand->poNode->GetNamedChild( "Descriptor_Table.#Bin_Function840#" );
760 :
761 46 : if( poBinEntry != NULL
762 : && EQUAL(poBinEntry->GetType(),"Edsc_BinFunction840")
763 : && EQUAL(poBinEntry->GetStringField( "binFunction.type.string" ),
764 : "BFUnique") )
765 10 : padfBinValues = HFAReadBFUniqueBins( poBinEntry, nNumBins );
766 :
767 46 : if( padfBinValues )
768 : {
769 10 : int nMaxValue = 0;
770 10 : int nMinValue = 1000000;
771 10 : int bAllInteger = TRUE;
772 :
773 915 : for( i = 0; i < nNumBins; i++ )
774 : {
775 905 : if( padfBinValues[i] != floor(padfBinValues[i]) )
776 0 : bAllInteger = FALSE;
777 :
778 905 : nMaxValue = MAX(nMaxValue,(int)padfBinValues[i]);
779 905 : nMinValue = MIN(nMinValue,(int)padfBinValues[i]);
780 : }
781 :
782 10 : if( nMinValue < 0 || nMaxValue > 1000 || !bAllInteger )
783 : {
784 0 : CPLFree( padfBinValues );
785 0 : CPLFree( panHistValues );
786 0 : CPLDebug( "HFA", "Unable to offer histogram because unique values list is not convenient to reform as HISTOBINVALUES." );
787 0 : return;
788 : }
789 :
790 10 : int nNewBins = nMaxValue + 1;
791 10 : int *panNewHistValues = (int *) CPLCalloc(sizeof(int),nNewBins);
792 :
793 915 : for( i = 0; i < nNumBins; i++ )
794 905 : panNewHistValues[(int) padfBinValues[i]] = panHistValues[i];
795 :
796 10 : CPLFree( panHistValues );
797 10 : panHistValues = panNewHistValues;
798 10 : nNumBins = nNewBins;
799 :
800 10 : SetMetadataItem( "STATISTICS_HISTOMIN", "0" );
801 : SetMetadataItem( "STATISTICS_HISTOMAX",
802 10 : CPLString().Printf("%d", nMaxValue ) );
803 : SetMetadataItem( "STATISTICS_HISTONUMBINS",
804 20 : CPLString().Printf("%d", nMaxValue+1 ) );
805 :
806 10 : CPLFree(padfBinValues);
807 10 : padfBinValues = NULL;
808 : }
809 :
810 : /* -------------------------------------------------------------------- */
811 : /* Format into HISTOBINVALUES text format. */
812 : /* -------------------------------------------------------------------- */
813 46 : unsigned int nBufSize = 1024;
814 46 : char * pszBinValues = (char *)CPLMalloc( nBufSize );
815 46 : int nBinValuesLen = 0;
816 46 : pszBinValues[0] = 0;
817 :
818 10641 : for ( int nBin = 0; nBin < nNumBins; ++nBin )
819 : {
820 : char szBuf[32];
821 10595 : snprintf( szBuf, 31, "%d", panHistValues[nBin] );
822 10595 : if ( ( nBinValuesLen + strlen( szBuf ) + 2 ) > nBufSize )
823 : {
824 3 : nBufSize *= 2;
825 3 : char* pszNewBinValues = (char *)VSIRealloc( pszBinValues, nBufSize );
826 3 : if (pszNewBinValues == NULL)
827 : {
828 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory");
829 0 : break;
830 : }
831 3 : pszBinValues = pszNewBinValues;
832 : }
833 10595 : strcat( pszBinValues+nBinValuesLen, szBuf );
834 10595 : strcat( pszBinValues+nBinValuesLen, "|" );
835 10595 : nBinValuesLen += strlen(pszBinValues+nBinValuesLen);
836 : }
837 :
838 46 : SetMetadataItem( "STATISTICS_HISTOBINVALUES", pszBinValues );
839 46 : CPLFree( panHistValues );
840 46 : CPLFree( pszBinValues );
841 : }
842 :
843 : /************************************************************************/
844 : /* GetNoDataValue() */
845 : /************************************************************************/
846 :
847 99 : double HFARasterBand::GetNoDataValue( int *pbSuccess )
848 :
849 : {
850 : double dfNoData;
851 :
852 99 : if( HFAGetBandNoData( hHFA, nBand, &dfNoData ) )
853 : {
854 15 : if( pbSuccess )
855 13 : *pbSuccess = TRUE;
856 15 : return dfNoData;
857 : }
858 : else
859 84 : return GDALPamRasterBand::GetNoDataValue( pbSuccess );
860 : }
861 :
862 : /************************************************************************/
863 : /* SetNoDataValue() */
864 : /************************************************************************/
865 :
866 6 : CPLErr HFARasterBand::SetNoDataValue( double dfValue )
867 : {
868 6 : return HFASetBandNoData( hHFA, nBand, dfValue );
869 : }
870 :
871 : /************************************************************************/
872 : /* GetMinimum() */
873 : /************************************************************************/
874 :
875 2 : double HFARasterBand::GetMinimum( int *pbSuccess )
876 :
877 : {
878 2 : const char *pszValue = GetMetadataItem( "STATISTICS_MINIMUM" );
879 :
880 2 : if( pszValue != NULL )
881 : {
882 2 : if( pbSuccess )
883 2 : *pbSuccess = TRUE;
884 2 : return CPLAtofM(pszValue);
885 : }
886 : else
887 : {
888 0 : return GDALRasterBand::GetMinimum( pbSuccess );
889 : }
890 : }
891 :
892 : /************************************************************************/
893 : /* GetMaximum() */
894 : /************************************************************************/
895 :
896 2 : double HFARasterBand::GetMaximum( int *pbSuccess )
897 :
898 : {
899 2 : const char *pszValue = GetMetadataItem( "STATISTICS_MAXIMUM" );
900 :
901 2 : if( pszValue != NULL )
902 : {
903 2 : if( pbSuccess )
904 2 : *pbSuccess = TRUE;
905 2 : return CPLAtofM(pszValue);
906 : }
907 : else
908 : {
909 0 : return GDALRasterBand::GetMaximum( pbSuccess );
910 : }
911 : }
912 :
913 : /************************************************************************/
914 : /* EstablishOverviews() */
915 : /* */
916 : /* Delayed population of overview information. */
917 : /************************************************************************/
918 :
919 140 : void HFARasterBand::EstablishOverviews()
920 :
921 : {
922 140 : if( nOverviews != -1 )
923 40 : return;
924 :
925 100 : nOverviews = HFAGetOverviewCount( hHFA, nBand );
926 100 : if( nOverviews > 0 )
927 : {
928 : papoOverviewBands = (HFARasterBand **)
929 21 : CPLMalloc(sizeof(void*)*nOverviews);
930 :
931 98 : for( int iOvIndex = 0; iOvIndex < nOverviews; iOvIndex++ )
932 : {
933 28 : papoOverviewBands[iOvIndex] =
934 56 : new HFARasterBand( (HFADataset *) poDS, nBand, iOvIndex );
935 : }
936 : }
937 : }
938 :
939 : /************************************************************************/
940 : /* GetOverviewCount() */
941 : /************************************************************************/
942 :
943 103 : int HFARasterBand::GetOverviewCount()
944 :
945 : {
946 103 : EstablishOverviews();
947 :
948 103 : if( nOverviews == 0 )
949 76 : return GDALRasterBand::GetOverviewCount();
950 : else
951 27 : return nOverviews;
952 : }
953 :
954 : /************************************************************************/
955 : /* GetOverview() */
956 : /************************************************************************/
957 :
958 29 : GDALRasterBand *HFARasterBand::GetOverview( int i )
959 :
960 : {
961 29 : EstablishOverviews();
962 :
963 29 : if( nOverviews == 0 )
964 0 : return GDALRasterBand::GetOverview( i );
965 29 : else if( i < 0 || i >= nOverviews )
966 0 : return NULL;
967 : else
968 29 : return papoOverviewBands[i];
969 : }
970 :
971 : /************************************************************************/
972 : /* IReadBlock() */
973 : /************************************************************************/
974 :
975 370 : CPLErr HFARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
976 : void * pImage )
977 :
978 : {
979 : CPLErr eErr;
980 :
981 370 : if( nThisOverview == -1 )
982 : eErr = HFAGetRasterBlockEx( hHFA, nBand, nBlockXOff, nBlockYOff,
983 : pImage,
984 336 : nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) );
985 : else
986 : {
987 : eErr = HFAGetOverviewRasterBlockEx( hHFA, nBand, nThisOverview,
988 : nBlockXOff, nBlockYOff,
989 : pImage,
990 34 : nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8));
991 : }
992 :
993 370 : if( eErr == CE_None && nHFADataType == EPT_u4 )
994 : {
995 0 : GByte *pabyData = (GByte *) pImage;
996 :
997 0 : for( int ii = nBlockXSize * nBlockYSize - 2; ii >= 0; ii -= 2 )
998 : {
999 0 : int k = ii>>1;
1000 0 : pabyData[ii+1] = (pabyData[k]>>4) & 0xf;
1001 0 : pabyData[ii] = (pabyData[k]) & 0xf;
1002 : }
1003 : }
1004 370 : if( eErr == CE_None && nHFADataType == EPT_u2 )
1005 : {
1006 4 : GByte *pabyData = (GByte *) pImage;
1007 :
1008 4100 : for( int ii = nBlockXSize * nBlockYSize - 4; ii >= 0; ii -= 4 )
1009 : {
1010 4096 : int k = ii>>2;
1011 4096 : pabyData[ii+3] = (pabyData[k]>>6) & 0x3;
1012 4096 : pabyData[ii+2] = (pabyData[k]>>4) & 0x3;
1013 4096 : pabyData[ii+1] = (pabyData[k]>>2) & 0x3;
1014 4096 : pabyData[ii] = (pabyData[k]) & 0x3;
1015 : }
1016 : }
1017 370 : if( eErr == CE_None && nHFADataType == EPT_u1)
1018 : {
1019 29 : GByte *pabyData = (GByte *) pImage;
1020 :
1021 118813 : for( int ii = nBlockXSize * nBlockYSize - 1; ii >= 0; ii-- )
1022 : {
1023 118784 : if( (pabyData[ii>>3] & (1 << (ii & 0x7))) )
1024 80597 : pabyData[ii] = 1;
1025 : else
1026 38187 : pabyData[ii] = 0;
1027 : }
1028 : }
1029 :
1030 370 : return eErr;
1031 : }
1032 :
1033 : /************************************************************************/
1034 : /* IWriteBlock() */
1035 : /************************************************************************/
1036 :
1037 107 : CPLErr HFARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
1038 : void * pImage )
1039 :
1040 : {
1041 107 : GByte *pabyOutBuf = (GByte *) pImage;
1042 :
1043 : /* -------------------------------------------------------------------- */
1044 : /* Do we need to pack 1/2/4 bit data? */
1045 : /* -------------------------------------------------------------------- */
1046 107 : if( nHFADataType == EPT_u1
1047 : || nHFADataType == EPT_u2
1048 : || nHFADataType == EPT_u4 )
1049 : {
1050 2 : int nPixCount = nBlockXSize * nBlockYSize;
1051 2 : pabyOutBuf = (GByte *) VSIMalloc2(nBlockXSize, nBlockYSize);
1052 2 : if (pabyOutBuf == NULL)
1053 0 : return CE_Failure;
1054 :
1055 2 : if( nHFADataType == EPT_u1 )
1056 : {
1057 1026 : for( int ii = 0; ii < nPixCount - 7; ii += 8 )
1058 : {
1059 1024 : int k = ii>>3;
1060 1024 : pabyOutBuf[k] =
1061 1024 : (((GByte *) pImage)[ii] & 0x1)
1062 1024 : | ((((GByte *) pImage)[ii+1]&0x1) << 1)
1063 1024 : | ((((GByte *) pImage)[ii+2]&0x1) << 2)
1064 1024 : | ((((GByte *) pImage)[ii+3]&0x1) << 3)
1065 1024 : | ((((GByte *) pImage)[ii+4]&0x1) << 4)
1066 1024 : | ((((GByte *) pImage)[ii+5]&0x1) << 5)
1067 1024 : | ((((GByte *) pImage)[ii+6]&0x1) << 6)
1068 7168 : | ((((GByte *) pImage)[ii+7]&0x1) << 7);
1069 : }
1070 : }
1071 0 : else if( nHFADataType == EPT_u2 )
1072 : {
1073 0 : for( int ii = 0; ii < nPixCount - 3; ii += 4 )
1074 : {
1075 0 : int k = ii>>2;
1076 0 : pabyOutBuf[k] =
1077 0 : (((GByte *) pImage)[ii] & 0x3)
1078 0 : | ((((GByte *) pImage)[ii+1]&0x3) << 2)
1079 0 : | ((((GByte *) pImage)[ii+2]&0x3) << 4)
1080 0 : | ((((GByte *) pImage)[ii+3]&0x3) << 6);
1081 : }
1082 : }
1083 0 : else if( nHFADataType == EPT_u4 )
1084 : {
1085 0 : for( int ii = 0; ii < nPixCount - 1; ii += 2 )
1086 : {
1087 0 : int k = ii>>1;
1088 0 : pabyOutBuf[k] =
1089 0 : (((GByte *) pImage)[ii] & 0xf)
1090 0 : | ((((GByte *) pImage)[ii+1]&0xf) << 4);
1091 : }
1092 : }
1093 : }
1094 :
1095 : /* -------------------------------------------------------------------- */
1096 : /* Actually write out. */
1097 : /* -------------------------------------------------------------------- */
1098 : CPLErr nRetCode;
1099 :
1100 107 : if( nThisOverview == -1 )
1101 : nRetCode = HFASetRasterBlock( hHFA, nBand, nBlockXOff, nBlockYOff,
1102 89 : pabyOutBuf );
1103 : else
1104 : nRetCode = HFASetOverviewRasterBlock( hHFA, nBand, nThisOverview,
1105 : nBlockXOff, nBlockYOff,
1106 18 : pabyOutBuf );
1107 :
1108 107 : if( pabyOutBuf != pImage )
1109 2 : CPLFree( pabyOutBuf );
1110 :
1111 107 : return nRetCode;
1112 : }
1113 :
1114 : /************************************************************************/
1115 : /* GetDescription() */
1116 : /************************************************************************/
1117 :
1118 154 : const char * HFARasterBand::GetDescription() const
1119 : {
1120 154 : const char *pszName = HFAGetBandName( hHFA, nBand );
1121 :
1122 154 : if( pszName == NULL )
1123 0 : return GDALPamRasterBand::GetDescription();
1124 : else
1125 154 : return pszName;
1126 : }
1127 :
1128 : /************************************************************************/
1129 : /* SetDescription() */
1130 : /************************************************************************/
1131 5 : void HFARasterBand::SetDescription( const char *pszName )
1132 : {
1133 5 : if( strlen(pszName) > 0 )
1134 5 : HFASetBandName( hHFA, nBand, pszName );
1135 5 : }
1136 :
1137 : /************************************************************************/
1138 : /* GetColorInterpretation() */
1139 : /************************************************************************/
1140 :
1141 50 : GDALColorInterp HFARasterBand::GetColorInterpretation()
1142 :
1143 : {
1144 50 : if( poCT != NULL )
1145 1 : return GCI_PaletteIndex;
1146 : else
1147 49 : return GCI_Undefined;
1148 : }
1149 :
1150 : /************************************************************************/
1151 : /* GetColorTable() */
1152 : /************************************************************************/
1153 :
1154 15 : GDALColorTable *HFARasterBand::GetColorTable()
1155 :
1156 : {
1157 15 : return poCT;
1158 : }
1159 :
1160 : /************************************************************************/
1161 : /* SetColorTable() */
1162 : /************************************************************************/
1163 :
1164 3 : CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
1165 :
1166 : {
1167 3 : if( GetAccess() == GA_ReadOnly )
1168 : {
1169 : CPLError( CE_Failure, CPLE_NoWriteAccess,
1170 0 : "Unable to set color table on read-only file." );
1171 0 : return CE_Failure;
1172 : }
1173 :
1174 : /* -------------------------------------------------------------------- */
1175 : /* Special case if we are clearing the color table. */
1176 : /* -------------------------------------------------------------------- */
1177 3 : if( poCTable == NULL )
1178 : {
1179 2 : delete poCT;
1180 2 : poCT = NULL;
1181 :
1182 2 : HFASetPCT( hHFA, nBand, 0, NULL, NULL, NULL, NULL );
1183 :
1184 2 : return CE_None;
1185 : }
1186 :
1187 : /* -------------------------------------------------------------------- */
1188 : /* Write out the colortable, and update the configuration. */
1189 : /* -------------------------------------------------------------------- */
1190 1 : int nColors = poCTable->GetColorEntryCount();
1191 :
1192 : double *padfRed, *padfGreen, *padfBlue, *padfAlpha;
1193 :
1194 1 : padfRed = (double *) CPLMalloc(sizeof(double) * nColors);
1195 1 : padfGreen = (double *) CPLMalloc(sizeof(double) * nColors);
1196 1 : padfBlue = (double *) CPLMalloc(sizeof(double) * nColors);
1197 1 : padfAlpha = (double *) CPLMalloc(sizeof(double) * nColors);
1198 :
1199 257 : for( int iColor = 0; iColor < nColors; iColor++ )
1200 : {
1201 : GDALColorEntry sRGB;
1202 :
1203 256 : poCTable->GetColorEntryAsRGB( iColor, &sRGB );
1204 :
1205 256 : padfRed[iColor] = sRGB.c1 / 255.0;
1206 256 : padfGreen[iColor] = sRGB.c2 / 255.0;
1207 256 : padfBlue[iColor] = sRGB.c3 / 255.0;
1208 256 : padfAlpha[iColor] = sRGB.c4 / 255.0;
1209 : }
1210 :
1211 : HFASetPCT( hHFA, nBand, nColors,
1212 1 : padfRed, padfGreen, padfBlue, padfAlpha);
1213 :
1214 1 : CPLFree( padfRed );
1215 1 : CPLFree( padfGreen );
1216 1 : CPLFree( padfBlue );
1217 1 : CPLFree( padfAlpha );
1218 :
1219 1 : if( poCT )
1220 0 : delete poCT;
1221 :
1222 1 : poCT = poCTable->Clone();
1223 :
1224 1 : return CE_None;
1225 : }
1226 :
1227 : /************************************************************************/
1228 : /* SetMetadata() */
1229 : /************************************************************************/
1230 :
1231 14 : CPLErr HFARasterBand::SetMetadata( char **papszMDIn, const char *pszDomain )
1232 :
1233 : {
1234 14 : bMetadataDirty = TRUE;
1235 :
1236 14 : return GDALPamRasterBand::SetMetadata( papszMDIn, pszDomain );
1237 : }
1238 :
1239 : /************************************************************************/
1240 : /* SetMetadata() */
1241 : /************************************************************************/
1242 :
1243 1035 : CPLErr HFARasterBand::SetMetadataItem( const char *pszTag, const char *pszValue,
1244 : const char *pszDomain )
1245 :
1246 : {
1247 1035 : bMetadataDirty = TRUE;
1248 :
1249 1035 : return GDALPamRasterBand::SetMetadataItem( pszTag, pszValue, pszDomain );
1250 : }
1251 :
1252 : /************************************************************************/
1253 : /* CleanOverviews() */
1254 : /************************************************************************/
1255 :
1256 1 : CPLErr HFARasterBand::CleanOverviews()
1257 :
1258 : {
1259 1 : if( nOverviews == 0 )
1260 0 : return CE_None;
1261 :
1262 : /* -------------------------------------------------------------------- */
1263 : /* Clear our reference to overviews as bands. */
1264 : /* -------------------------------------------------------------------- */
1265 : int iOverview;
1266 :
1267 2 : for( iOverview = 0; iOverview < nOverviews; iOverview++ )
1268 1 : delete papoOverviewBands[iOverview];
1269 :
1270 1 : CPLFree( papoOverviewBands );
1271 1 : papoOverviewBands = NULL;
1272 1 : nOverviews = 0;
1273 :
1274 : /* -------------------------------------------------------------------- */
1275 : /* Search for any RRDNamesList and destroy it. */
1276 : /* -------------------------------------------------------------------- */
1277 1 : HFABand *poBand = hHFA->papoBand[nBand-1];
1278 1 : HFAEntry *poEntry = poBand->poNode->GetNamedChild( "RRDNamesList" );
1279 1 : if( poEntry != NULL )
1280 : {
1281 1 : poEntry->RemoveAndDestroy();
1282 : }
1283 :
1284 : /* -------------------------------------------------------------------- */
1285 : /* Destroy and subsample layers under our band. */
1286 : /* -------------------------------------------------------------------- */
1287 : HFAEntry *poChild;
1288 6 : for( poChild = poBand->poNode->GetChild();
1289 : poChild != NULL; )
1290 : {
1291 4 : HFAEntry *poNext = poChild->GetNext();
1292 :
1293 4 : if( EQUAL(poChild->GetType(),"Eimg_Layer_SubSample") )
1294 0 : poChild->RemoveAndDestroy();
1295 :
1296 4 : poChild = poNext;
1297 : }
1298 :
1299 : /* -------------------------------------------------------------------- */
1300 : /* Clean up dependent file if we are the last band under the */
1301 : /* assumption there will be nothing else referencing it after */
1302 : /* this. */
1303 : /* -------------------------------------------------------------------- */
1304 1 : if( hHFA->psDependent != hHFA && hHFA->psDependent != NULL )
1305 : {
1306 : CPLString osFilename =
1307 : CPLFormFilename( hHFA->psDependent->pszPath,
1308 1 : hHFA->psDependent->pszFilename, NULL );
1309 :
1310 1 : HFAClose( hHFA->psDependent );
1311 1 : hHFA->psDependent = NULL;
1312 :
1313 1 : CPLDebug( "HFA", "Unlink(%s)", osFilename.c_str() );
1314 1 : VSIUnlink( osFilename );
1315 : }
1316 :
1317 1 : return CE_None;
1318 : }
1319 :
1320 : /************************************************************************/
1321 : /* BuildOverviews() */
1322 : /************************************************************************/
1323 :
1324 8 : CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
1325 : int nReqOverviews, int *panOverviewList,
1326 : GDALProgressFunc pfnProgress,
1327 : void *pProgressData )
1328 :
1329 : {
1330 : int iOverview;
1331 : GDALRasterBand **papoOvBands;
1332 8 : int bNoRegen = FALSE;
1333 :
1334 8 : EstablishOverviews();
1335 :
1336 8 : if( nThisOverview != -1 )
1337 : {
1338 : CPLError( CE_Failure, CPLE_AppDefined,
1339 0 : "Attempt to build overviews on an overview layer." );
1340 :
1341 0 : return CE_Failure;
1342 : }
1343 :
1344 8 : if( nReqOverviews == 0 )
1345 1 : return CleanOverviews();
1346 :
1347 7 : papoOvBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nReqOverviews);
1348 :
1349 7 : if( EQUALN(pszResampling,"NO_REGEN:",9) )
1350 : {
1351 2 : pszResampling += 9;
1352 2 : bNoRegen = TRUE;
1353 : }
1354 :
1355 : /* -------------------------------------------------------------------- */
1356 : /* Loop over overview levels requested. */
1357 : /* -------------------------------------------------------------------- */
1358 15 : for( iOverview = 0; iOverview < nReqOverviews; iOverview++ )
1359 : {
1360 : /* -------------------------------------------------------------------- */
1361 : /* Find this overview level. */
1362 : /* -------------------------------------------------------------------- */
1363 8 : int i, iResult = -1, nReqOvLevel;
1364 :
1365 : nReqOvLevel =
1366 8 : GDALOvLevelAdjust(panOverviewList[iOverview],nRasterXSize);
1367 :
1368 13 : for( i = 0; i < nOverviews && papoOvBands[iOverview] == NULL; i++ )
1369 : {
1370 : int nThisOvLevel;
1371 :
1372 : nThisOvLevel = (int) (0.5 + GetXSize()
1373 5 : / (double) papoOverviewBands[i]->GetXSize());
1374 :
1375 5 : if( nReqOvLevel == nThisOvLevel )
1376 1 : papoOvBands[iOverview] = papoOverviewBands[i];
1377 : }
1378 :
1379 : /* -------------------------------------------------------------------- */
1380 : /* If this overview level does not yet exist, create it now. */
1381 : /* -------------------------------------------------------------------- */
1382 8 : if( papoOvBands[iOverview] == NULL )
1383 : {
1384 : iResult = HFACreateOverview( hHFA, nBand,
1385 : panOverviewList[iOverview],
1386 7 : pszResampling );
1387 7 : if( iResult < 0 )
1388 0 : return CE_Failure;
1389 :
1390 7 : nOverviews = iResult + 1;
1391 : papoOverviewBands = (HFARasterBand **)
1392 7 : CPLRealloc( papoOverviewBands, sizeof(void*) * nOverviews);
1393 7 : papoOverviewBands[iResult] = new HFARasterBand(
1394 14 : (HFADataset *) poDS, nBand, iResult );
1395 :
1396 7 : papoOvBands[iOverview] = papoOverviewBands[iResult];
1397 : }
1398 :
1399 : }
1400 :
1401 : /* -------------------------------------------------------------------- */
1402 : /* Regenerate the overviews. */
1403 : /* -------------------------------------------------------------------- */
1404 7 : CPLErr eErr = CE_None;
1405 :
1406 7 : if( !bNoRegen )
1407 : eErr = GDALRegenerateOverviews( (GDALRasterBandH) this,
1408 : nReqOverviews,
1409 : (GDALRasterBandH *) papoOvBands,
1410 : pszResampling,
1411 5 : pfnProgress, pProgressData );
1412 :
1413 7 : CPLFree( papoOvBands );
1414 :
1415 7 : return eErr;
1416 : }
1417 :
1418 : /************************************************************************/
1419 : /* GetDefaultHistogram() */
1420 : /************************************************************************/
1421 :
1422 : CPLErr
1423 3 : HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
1424 : int *pnBuckets, int ** ppanHistogram,
1425 : int bForce,
1426 : GDALProgressFunc pfnProgress,
1427 : void *pProgressData)
1428 :
1429 : {
1430 5 : if( GetMetadataItem( "STATISTICS_HISTOBINVALUES" ) != NULL
1431 1 : && GetMetadataItem( "STATISTICS_HISTOMIN" ) != NULL
1432 1 : && GetMetadataItem( "STATISTICS_HISTOMAX" ) != NULL )
1433 : {
1434 : int i;
1435 : const char *pszNextBin;
1436 : const char *pszBinValues =
1437 1 : GetMetadataItem( "STATISTICS_HISTOBINVALUES" );
1438 :
1439 1 : *pdfMin = atof(GetMetadataItem("STATISTICS_HISTOMIN"));
1440 1 : *pdfMax = atof(GetMetadataItem("STATISTICS_HISTOMAX"));
1441 :
1442 1 : *pnBuckets = 0;
1443 573 : for( i = 0; pszBinValues[i] != '\0'; i++ )
1444 : {
1445 572 : if( pszBinValues[i] == '|' )
1446 220 : (*pnBuckets)++;
1447 : }
1448 :
1449 1 : *ppanHistogram = (int *) CPLCalloc(sizeof(int),*pnBuckets);
1450 :
1451 1 : pszNextBin = pszBinValues;
1452 221 : for( i = 0; i < *pnBuckets; i++ )
1453 : {
1454 220 : (*ppanHistogram)[i] = atoi(pszNextBin);
1455 :
1456 792 : while( *pszNextBin != '|' && *pszNextBin != '\0' )
1457 352 : pszNextBin++;
1458 220 : if( *pszNextBin == '|' )
1459 220 : pszNextBin++;
1460 : }
1461 :
1462 : // Adjust min/max to reflect outer edges of buckets.
1463 1 : double dfBucketWidth = (*pdfMax - *pdfMin) / (*pnBuckets-1);
1464 1 : *pdfMax += 0.5 * dfBucketWidth;
1465 1 : *pdfMin -= 0.5 * dfBucketWidth;
1466 :
1467 1 : return CE_None;
1468 : }
1469 : else
1470 : return GDALPamRasterBand::GetDefaultHistogram( pdfMin, pdfMax,
1471 : pnBuckets,ppanHistogram,
1472 : bForce,
1473 : pfnProgress,
1474 2 : pProgressData );
1475 : }
1476 :
1477 : /************************************************************************/
1478 : /* SetDefaultRAT() */
1479 : /************************************************************************/
1480 :
1481 1 : CPLErr HFARasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
1482 :
1483 : {
1484 1 : return WriteNamedRAT( "Descriptor_Table", poRAT );
1485 : }
1486 :
1487 : /************************************************************************/
1488 : /* GetDefaultRAT() */
1489 : /************************************************************************/
1490 :
1491 16 : const GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
1492 :
1493 : {
1494 16 : return poDefaultRAT;
1495 : }
1496 :
1497 : /************************************************************************/
1498 : /* ReadNamedRAT() */
1499 : /************************************************************************/
1500 :
1501 485 : GDALRasterAttributeTable *HFARasterBand::ReadNamedRAT( const char *pszName )
1502 :
1503 : {
1504 : /* -------------------------------------------------------------------- */
1505 : /* Find the requested table. */
1506 : /* -------------------------------------------------------------------- */
1507 485 : HFAEntry *poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild(pszName);
1508 :
1509 485 : if( poDT == NULL )
1510 431 : return NULL;
1511 :
1512 : /* -------------------------------------------------------------------- */
1513 : /* Create a corresponding RAT. */
1514 : /* -------------------------------------------------------------------- */
1515 54 : GDALRasterAttributeTable *poRAT = NULL;
1516 54 : int nRowCount = poDT->GetIntField( "numRows" );
1517 :
1518 54 : poRAT = new GDALRasterAttributeTable();
1519 :
1520 : /* -------------------------------------------------------------------- */
1521 : /* Scan under table for columns. */
1522 : /* -------------------------------------------------------------------- */
1523 : HFAEntry *poDTChild;
1524 :
1525 181 : for( poDTChild = poDT->GetChild();
1526 : poDTChild != NULL;
1527 : poDTChild = poDTChild->GetNext() )
1528 : {
1529 : int i;
1530 :
1531 127 : if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction") )
1532 : {
1533 37 : double dfMax = poDTChild->GetDoubleField( "maxLimit" );
1534 37 : double dfMin = poDTChild->GetDoubleField( "minLimit" );
1535 37 : int nBinCount = poDTChild->GetIntField( "numBins" );
1536 :
1537 37 : if( nBinCount == nRowCount
1538 : && dfMax != dfMin && nBinCount != 0 )
1539 : poRAT->SetLinearBinning( dfMin,
1540 37 : (dfMax-dfMin) / (nBinCount-1) );
1541 : }
1542 :
1543 127 : if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction840")
1544 : && EQUAL(poDTChild->GetStringField( "binFunction.type.string" ),
1545 : "BFUnique") )
1546 : {
1547 10 : double *padfBinValues = HFAReadBFUniqueBins( poDTChild, nRowCount );
1548 :
1549 10 : if( padfBinValues != NULL )
1550 : {
1551 10 : poRAT->CreateColumn( "BinValues", GFT_Real, GFU_MinMax );
1552 915 : for( i = 0; i < nRowCount; i++ )
1553 : poRAT->SetValue( i, poRAT->GetColumnCount()-1,
1554 905 : padfBinValues[i] );
1555 :
1556 10 : CPLFree( padfBinValues );
1557 : }
1558 : }
1559 :
1560 127 : if( !EQUAL(poDTChild->GetType(),"Edsc_Column") )
1561 47 : continue;
1562 :
1563 80 : int nOffset = poDTChild->GetIntField( "columnDataPtr" );
1564 80 : const char * pszType = poDTChild->GetStringField( "dataType" );
1565 80 : GDALRATFieldUsage eType = GFU_Generic;
1566 :
1567 80 : if( pszType == NULL || nOffset == 0 )
1568 0 : continue;
1569 :
1570 80 : if( EQUAL(poDTChild->GetName(),"Histogram") )
1571 48 : eType = GFU_Generic;
1572 32 : else if( EQUAL(poDTChild->GetName(),"Red") )
1573 7 : eType = GFU_Red;
1574 25 : else if( EQUAL(poDTChild->GetName(),"Green") )
1575 7 : eType = GFU_Green;
1576 18 : else if( EQUAL(poDTChild->GetName(),"Blue") )
1577 7 : eType = GFU_Blue;
1578 11 : else if( EQUAL(poDTChild->GetName(),"Alpha") )
1579 0 : eType = GFU_Alpha;
1580 11 : else if( EQUAL(poDTChild->GetName(),"Class_Names") )
1581 0 : eType = GFU_Name;
1582 :
1583 80 : if( EQUAL(pszType,"real") )
1584 : {
1585 68 : double *padfColData = (double*)VSIMalloc2(nRowCount, sizeof(double));
1586 68 : if (nRowCount != 0 && padfColData == NULL)
1587 : {
1588 : CPLError( CE_Failure, CPLE_OutOfMemory,
1589 0 : "HFARasterBand::ReadNamedRAT : Out of memory");
1590 0 : delete poRAT;
1591 0 : return NULL;
1592 : }
1593 :
1594 68 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
1595 68 : if ((int)VSIFReadL( padfColData, sizeof(double), nRowCount, hHFA->fp ) != nRowCount)
1596 : {
1597 : CPLError( CE_Failure, CPLE_AppDefined,
1598 0 : "HFARasterBand::ReadNamedRAT : Cannot read values");
1599 0 : CPLFree(padfColData);
1600 0 : delete poRAT;
1601 0 : return NULL;
1602 : }
1603 : #ifdef CPL_MSB
1604 : GDALSwapWords( padfColData, 8, nRowCount, 8 );
1605 : #endif
1606 68 : poRAT->CreateColumn( poDTChild->GetName(), GFT_Real, eType );
1607 10184 : for( i = 0; i < nRowCount; i++ )
1608 10116 : poRAT->SetValue( i, poRAT->GetColumnCount()-1, padfColData[i]);
1609 :
1610 68 : CPLFree( padfColData );
1611 : }
1612 12 : else if( EQUAL(pszType,"string") )
1613 : {
1614 1 : int nMaxNumChars = poDTChild->GetIntField( "maxNumChars" );
1615 1 : char *pachColData = (char*)VSICalloc(nRowCount+1,nMaxNumChars);
1616 1 : if (pachColData == NULL)
1617 : {
1618 : CPLError( CE_Failure, CPLE_OutOfMemory,
1619 0 : "HFARasterBand::ReadNamedRAT : Out of memory");
1620 0 : delete poRAT;
1621 0 : return NULL;
1622 : }
1623 :
1624 1 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
1625 1 : if ((int)VSIFReadL( pachColData, nMaxNumChars, nRowCount, hHFA->fp ) != nRowCount)
1626 : {
1627 : CPLError( CE_Failure, CPLE_AppDefined,
1628 0 : "HFARasterBand::ReadNamedRAT : Cannot read values");
1629 0 : CPLFree(pachColData);
1630 0 : delete poRAT;
1631 0 : return NULL;
1632 : }
1633 :
1634 1 : poRAT->CreateColumn(poDTChild->GetName(),GFT_String,eType);
1635 219 : for( i = 0; i < nRowCount; i++ )
1636 : {
1637 218 : CPLString oRowVal;
1638 :
1639 218 : oRowVal.assign( pachColData+nMaxNumChars*i, nMaxNumChars );
1640 : poRAT->SetValue( i, poRAT->GetColumnCount()-1,
1641 218 : oRowVal.c_str() );
1642 : }
1643 :
1644 1 : CPLFree( pachColData );
1645 : }
1646 11 : else if( EQUALN(pszType,"int",3) )
1647 : {
1648 11 : GInt32 *panColData = (GInt32*)VSIMalloc2(nRowCount, sizeof(GInt32));
1649 11 : if (nRowCount != 0 && panColData == NULL)
1650 : {
1651 : CPLError( CE_Failure, CPLE_OutOfMemory,
1652 0 : "HFARasterBand::ReadNamedRAT : Out of memory");
1653 0 : delete poRAT;
1654 0 : return NULL;
1655 : }
1656 :
1657 11 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
1658 11 : if ((int)VSIFReadL( panColData, sizeof(GInt32), nRowCount, hHFA->fp ) != nRowCount)
1659 : {
1660 : CPLError( CE_Failure, CPLE_AppDefined,
1661 0 : "HFARasterBand::ReadNamedRAT : Cannot read values");
1662 0 : CPLFree(panColData);
1663 0 : delete poRAT;
1664 0 : return NULL;
1665 : }
1666 : #ifdef CPL_MSB
1667 : GDALSwapWords( panColData, 4, nRowCount, 4 );
1668 : #endif
1669 11 : poRAT->CreateColumn(poDTChild->GetName(),GFT_Integer,eType);
1670 2767 : for( i = 0; i < nRowCount; i++ )
1671 2756 : poRAT->SetValue( i, poRAT->GetColumnCount()-1, panColData[i] );
1672 :
1673 11 : CPLFree( panColData );
1674 : }
1675 : }
1676 :
1677 54 : return poRAT;
1678 : }
1679 :
1680 : /************************************************************************/
1681 : /* WriteNamedRAT() */
1682 : /************************************************************************/
1683 :
1684 1 : CPLErr HFARasterBand::WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT )
1685 : {
1686 : /* -------------------------------------------------------------------- */
1687 : /* Find the requested table. */
1688 : /* -------------------------------------------------------------------- */
1689 1 : HFAEntry * poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild( "Descriptor_Table" );
1690 1 : if( poDT == NULL || !EQUAL(poDT->GetType(),"Edsc_Table") )
1691 1 : poDT = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
1692 : "Descriptor_Table", "Edsc_Table",
1693 2 : hHFA->papoBand[nBand-1]->poNode );
1694 :
1695 :
1696 1 : int nRowCount = poRAT->GetRowCount();
1697 :
1698 1 : poDT->SetIntField( "numrows", nRowCount );
1699 : /* Check if binning is set on this RAT */
1700 : double dfBinSize, dfRow0Min;
1701 1 : if(poRAT->GetLinearBinning( &dfRow0Min, &dfBinSize))
1702 : {
1703 : /* then it should have an Edsc_BinFunction */
1704 0 : HFAEntry *poBinFunction = poDT->GetNamedChild( "#Bin_Function#" );
1705 0 : if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
1706 0 : poBinFunction = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
1707 : "#Bin_Function#", "Edsc_BinFunction",
1708 0 : poDT );
1709 :
1710 0 : poBinFunction->SetStringField("binFunction", "direct");
1711 0 : poBinFunction->SetDoubleField("minLimit",dfRow0Min);
1712 0 : poBinFunction->SetDoubleField("maxLimit",(nRowCount -1)*dfBinSize+dfRow0Min);
1713 0 : poBinFunction->SetIntField("numBins",nRowCount);
1714 : }
1715 :
1716 : /* -------------------------------------------------------------------- */
1717 : /* Loop through each column in the RAT */
1718 : /* -------------------------------------------------------------------- */
1719 7 : for(int col = 0; col < poRAT->GetColumnCount(); col++)
1720 : {
1721 6 : const char *pszName = NULL;
1722 :
1723 6 : if( poRAT->GetUsageOfCol(col) == GFU_Red )
1724 : {
1725 1 : pszName = "Red";
1726 : }
1727 5 : else if( poRAT->GetUsageOfCol(col) == GFU_Green )
1728 : {
1729 1 : pszName = "Green";
1730 : }
1731 4 : else if( poRAT->GetUsageOfCol(col) == GFU_Blue )
1732 : {
1733 1 : pszName = "Blue";
1734 : }
1735 3 : else if( poRAT->GetUsageOfCol(col) == GFU_Alpha )
1736 : {
1737 0 : pszName = "Alpha";
1738 : }
1739 3 : else if( poRAT->GetUsageOfCol(col) == GFU_PixelCount )
1740 : {
1741 0 : pszName = "Histogram";
1742 : }
1743 3 : else if( poRAT->GetUsageOfCol(col) == GFU_Name )
1744 : {
1745 0 : pszName = "Class_Names";
1746 : }
1747 : else
1748 : {
1749 3 : pszName = poRAT->GetNameOfCol(col);
1750 : }
1751 :
1752 : /* -------------------------------------------------------------------- */
1753 : /* Check to see if a column with pszName exists and create if */
1754 : /* if necessary. */
1755 : /* -------------------------------------------------------------------- */
1756 :
1757 : HFAEntry *poColumn;
1758 6 : poColumn = poDT->GetNamedChild(pszName);
1759 :
1760 6 : if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
1761 6 : poColumn = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
1762 : pszName, "Edsc_Column",
1763 12 : poDT );
1764 :
1765 :
1766 6 : poColumn->SetIntField( "numRows", nRowCount );
1767 :
1768 6 : if( poRAT->GetTypeOfCol(col) == GFT_Real )
1769 : {
1770 6 : int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
1771 12 : nRowCount * sizeof(double) );
1772 6 : poColumn->SetIntField( "columnDataPtr", nOffset );
1773 6 : poColumn->SetStringField( "dataType", "real" );
1774 :
1775 6 : double *padfColData = (double*)CPLCalloc( nRowCount, sizeof(double) );
1776 456 : for( int i = 0; i < nRowCount; i++)
1777 : {
1778 450 : padfColData[i] = poRAT->GetValueAsDouble(i,col);
1779 : }
1780 : #ifdef CPL_MSB
1781 : GDALSwapWords( padfColData, 8, nRowCount, 8 );
1782 : #endif
1783 6 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
1784 6 : VSIFWriteL( padfColData, nRowCount, sizeof(double), hHFA->fp );
1785 6 : CPLFree( padfColData );
1786 : }
1787 0 : else if( poRAT->GetTypeOfCol(col) == GFT_String )
1788 : {
1789 0 : unsigned int nMaxNumChars = 0;
1790 : /* find the length of the longest string */
1791 0 : for( int i = 0; i < nRowCount; i++)
1792 : {
1793 0 : if(nMaxNumChars < strlen(poRAT->GetValueAsString(i,col)))
1794 : {
1795 0 : nMaxNumChars = strlen(poRAT->GetValueAsString(i,col));
1796 : }
1797 : }
1798 :
1799 0 : int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
1800 0 : (nRowCount+1) * nMaxNumChars );
1801 0 : poColumn->SetIntField( "columnDataPtr", nOffset );
1802 0 : poColumn->SetStringField( "dataType", "string" );
1803 0 : poColumn->SetIntField( "maxNumChars", nMaxNumChars );
1804 :
1805 0 : char *pachColData = (char*)CPLCalloc(nRowCount+1,nMaxNumChars);
1806 0 : for( int i = 0; i < nRowCount; i++)
1807 : {
1808 0 : strcpy(&pachColData[nMaxNumChars*i],poRAT->GetValueAsString(i,col));
1809 : }
1810 0 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
1811 0 : VSIFWriteL( pachColData, nRowCount, nMaxNumChars, hHFA->fp );
1812 0 : CPLFree( pachColData );
1813 : }
1814 0 : else if (poRAT->GetTypeOfCol(col) == GFT_Integer)
1815 : {
1816 0 : int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
1817 0 : nRowCount * sizeof(GInt32) );
1818 0 : poColumn->SetIntField( "columnDataPtr", nOffset );
1819 0 : poColumn->SetStringField( "dataType", "integer" );
1820 :
1821 0 : GInt32 *panColData = (GInt32*)CPLCalloc(nRowCount, sizeof(GInt32));
1822 0 : for( int i = 0; i < nRowCount; i++)
1823 : {
1824 0 : panColData[i] = poRAT->GetValueAsInt(i,col);
1825 : }
1826 : #ifdef CPL_MSB
1827 : GDALSwapWords( panColData, 4, nRowCount, 4 );
1828 : #endif
1829 0 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
1830 0 : VSIFWriteL( panColData, nRowCount, sizeof(GInt32), hHFA->fp );
1831 0 : CPLFree( panColData );
1832 : }
1833 : else
1834 : {
1835 : /* can't deal with any of the others yet */
1836 : CPLError( CE_Failure, CPLE_NotSupported,
1837 0 : "Writing this data type in a column is not supported for this Raster Attribute Table.");
1838 : }
1839 : }
1840 :
1841 1 : return CE_None;
1842 : }
1843 :
1844 :
1845 : /************************************************************************/
1846 : /* ==================================================================== */
1847 : /* HFADataset */
1848 : /* ==================================================================== */
1849 : /************************************************************************/
1850 :
1851 : /************************************************************************/
1852 : /* HFADataset() */
1853 : /************************************************************************/
1854 :
1855 379 : HFADataset::HFADataset()
1856 :
1857 : {
1858 379 : hHFA = NULL;
1859 379 : bGeoDirty = FALSE;
1860 379 : pszProjection = CPLStrdup("");
1861 379 : bMetadataDirty = FALSE;
1862 379 : bIgnoreUTM = FALSE;
1863 379 : bForceToPEString = FALSE;
1864 :
1865 379 : nGCPCount = 0;
1866 379 : }
1867 :
1868 : /************************************************************************/
1869 : /* ~HFADataset() */
1870 : /************************************************************************/
1871 :
1872 379 : HFADataset::~HFADataset()
1873 :
1874 : {
1875 379 : FlushCache();
1876 :
1877 : /* -------------------------------------------------------------------- */
1878 : /* Destroy the raster bands if they exist. We forcably clean */
1879 : /* them up now to avoid any effort to write to them after the */
1880 : /* file is closed. */
1881 : /* -------------------------------------------------------------------- */
1882 : int i;
1883 :
1884 829 : for( i = 0; i < nBands && papoBands != NULL; i++ )
1885 : {
1886 450 : if( papoBands[i] != NULL )
1887 450 : delete papoBands[i];
1888 : }
1889 :
1890 379 : CPLFree( papoBands );
1891 379 : papoBands = NULL;
1892 :
1893 : /* -------------------------------------------------------------------- */
1894 : /* Close the file */
1895 : /* -------------------------------------------------------------------- */
1896 379 : if( hHFA != NULL )
1897 : {
1898 379 : HFAClose( hHFA );
1899 379 : hHFA = NULL;
1900 : }
1901 :
1902 : /* -------------------------------------------------------------------- */
1903 : /* Cleanup */
1904 : /* -------------------------------------------------------------------- */
1905 379 : CPLFree( pszProjection );
1906 379 : if( nGCPCount > 0 )
1907 1 : GDALDeinitGCPs( 36, asGCPList );
1908 379 : }
1909 :
1910 : /************************************************************************/
1911 : /* FlushCache() */
1912 : /************************************************************************/
1913 :
1914 384 : void HFADataset::FlushCache()
1915 :
1916 : {
1917 384 : GDALPamDataset::FlushCache();
1918 :
1919 384 : if( eAccess != GA_Update )
1920 245 : return;
1921 :
1922 139 : if( bGeoDirty )
1923 92 : WriteProjection();
1924 :
1925 139 : if( bMetadataDirty && GetMetadata() != NULL )
1926 : {
1927 43 : HFASetMetadata( hHFA, 0, GetMetadata() );
1928 43 : bMetadataDirty = FALSE;
1929 : }
1930 :
1931 312 : for( int iBand = 0; iBand < nBands; iBand++ )
1932 : {
1933 173 : HFARasterBand *poBand = (HFARasterBand *) GetRasterBand(iBand+1);
1934 173 : if( poBand->bMetadataDirty && poBand->GetMetadata() != NULL )
1935 : {
1936 7 : HFASetMetadata( hHFA, iBand+1, poBand->GetMetadata() );
1937 7 : poBand->bMetadataDirty = FALSE;
1938 : }
1939 : }
1940 :
1941 139 : if( nGCPCount > 0 )
1942 : {
1943 0 : GDALDeinitGCPs( nGCPCount, asGCPList );
1944 : }
1945 : }
1946 :
1947 : /************************************************************************/
1948 : /* WriteProjection() */
1949 : /************************************************************************/
1950 :
1951 92 : CPLErr HFADataset::WriteProjection()
1952 :
1953 : {
1954 : Eprj_Datum sDatum;
1955 : Eprj_ProParameters sPro;
1956 : Eprj_MapInfo sMapInfo;
1957 92 : OGRSpatialReference oSRS;
1958 92 : OGRSpatialReference *poGeogSRS = NULL;
1959 : int bHaveSRS;
1960 92 : char *pszP = pszProjection;
1961 92 : int bPEStringStored = FALSE;
1962 :
1963 92 : bGeoDirty = FALSE;
1964 :
1965 92 : if( pszProjection != NULL && strlen(pszProjection) > 0
1966 : && oSRS.importFromWkt( &pszP ) == OGRERR_NONE )
1967 80 : bHaveSRS = TRUE;
1968 : else
1969 12 : bHaveSRS = FALSE;
1970 :
1971 : /* -------------------------------------------------------------------- */
1972 : /* Initialize projection and datum. */
1973 : /* -------------------------------------------------------------------- */
1974 92 : memset( &sPro, 0, sizeof(sPro) );
1975 92 : memset( &sDatum, 0, sizeof(sDatum) );
1976 92 : memset( &sMapInfo, 0, sizeof(sMapInfo) );
1977 :
1978 : /* -------------------------------------------------------------------- */
1979 : /* Collect datum information. */
1980 : /* -------------------------------------------------------------------- */
1981 92 : if( bHaveSRS )
1982 : {
1983 80 : poGeogSRS = oSRS.CloneGeogCS();
1984 : }
1985 :
1986 92 : if( poGeogSRS )
1987 : {
1988 : int i;
1989 :
1990 80 : sDatum.datumname = (char *) poGeogSRS->GetAttrValue( "GEOGCS|DATUM" );
1991 :
1992 : /* WKT to Imagine translation */
1993 235 : for( i = 0; apszDatumMap[i] != NULL; i += 2 )
1994 : {
1995 220 : if( EQUAL(sDatum.datumname,apszDatumMap[i+1]) )
1996 : {
1997 65 : sDatum.datumname = (char *) apszDatumMap[i];
1998 65 : break;
1999 : }
2000 : }
2001 :
2002 : /* Map some EPSG datum codes directly to Imagine names */
2003 80 : int nGCS = poGeogSRS->GetEPSGGeogCS();
2004 :
2005 80 : if( nGCS == 4326 )
2006 39 : sDatum.datumname = (char*) "WGS 84";
2007 80 : if( nGCS == 4322 )
2008 0 : sDatum.datumname = (char*) "WGS 1972";
2009 80 : if( nGCS == 4267 )
2010 24 : sDatum.datumname = (char*) "NAD27";
2011 80 : if( nGCS == 4269 )
2012 2 : sDatum.datumname = (char*) "NAD83";
2013 80 : if( nGCS == 4283 )
2014 0 : sDatum.datumname = (char*) "GDA94";
2015 :
2016 80 : if( poGeogSRS->GetTOWGS84( sDatum.params ) == OGRERR_NONE )
2017 11 : sDatum.type = EPRJ_DATUM_PARAMETRIC;
2018 69 : else if( EQUAL(sDatum.datumname,"NAD27") )
2019 : {
2020 24 : sDatum.type = EPRJ_DATUM_GRID;
2021 24 : sDatum.gridname = (char*) "nadcon.dat";
2022 : }
2023 : else
2024 : {
2025 : /* we will default to this (effectively WGS84) for now */
2026 45 : sDatum.type = EPRJ_DATUM_PARAMETRIC;
2027 : }
2028 :
2029 : /* Verify if we need to write a ESRI PE string */
2030 80 : bPEStringStored = WritePeStringIfNeeded(&oSRS, hHFA);
2031 :
2032 : sPro.proSpheroid.sphereName = (char *)
2033 80 : poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
2034 80 : sPro.proSpheroid.a = poGeogSRS->GetSemiMajor();
2035 80 : sPro.proSpheroid.b = poGeogSRS->GetSemiMinor();
2036 80 : sPro.proSpheroid.radius = sPro.proSpheroid.a;
2037 :
2038 80 : double a2 = sPro.proSpheroid.a*sPro.proSpheroid.a;
2039 80 : double b2 = sPro.proSpheroid.b*sPro.proSpheroid.b;
2040 :
2041 80 : sPro.proSpheroid.eSquared = (a2-b2)/a2;
2042 : }
2043 :
2044 : /* -------------------------------------------------------------------- */
2045 : /* Recognise various projections. */
2046 : /* -------------------------------------------------------------------- */
2047 92 : const char * pszProjName = NULL;
2048 :
2049 92 : if( bHaveSRS )
2050 80 : pszProjName = oSRS.GetAttrValue( "PROJCS|PROJECTION" );
2051 :
2052 92 : if( bForceToPEString && !bPEStringStored )
2053 : {
2054 0 : char *pszPEString = NULL;
2055 0 : oSRS.morphToESRI();
2056 0 : oSRS.exportToWkt( &pszPEString );
2057 : // need to transform this into ESRI format.
2058 0 : HFASetPEString( hHFA, pszPEString );
2059 0 : CPLFree( pszPEString );
2060 :
2061 0 : bPEStringStored = TRUE;
2062 : }
2063 92 : else if( pszProjName == NULL )
2064 : {
2065 47 : if( bHaveSRS && oSRS.IsGeographic() )
2066 : {
2067 35 : sPro.proNumber = EPRJ_LATLONG;
2068 35 : sPro.proName = (char*) "Geographic (Lat/Lon)";
2069 : }
2070 : }
2071 :
2072 : /* FIXME/NOTDEF/TODO: Add State Plane */
2073 45 : else if( !bIgnoreUTM && oSRS.GetUTMZone( NULL ) != 0 )
2074 : {
2075 : int bNorth, nZone;
2076 :
2077 24 : nZone = oSRS.GetUTMZone( &bNorth );
2078 24 : sPro.proNumber = EPRJ_UTM;
2079 24 : sPro.proName = (char*) "UTM";
2080 24 : sPro.proZone = nZone;
2081 24 : if( bNorth )
2082 24 : sPro.proParams[3] = 1.0;
2083 : else
2084 0 : sPro.proParams[3] = -1.0;
2085 : }
2086 :
2087 21 : else if( EQUAL(pszProjName,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
2088 : {
2089 0 : sPro.proNumber = EPRJ_ALBERS_CONIC_EQUAL_AREA;
2090 0 : sPro.proName = (char*) "Albers Conical Equal Area";
2091 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2092 0 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
2093 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2094 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2095 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2096 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2097 : }
2098 21 : else if( EQUAL(pszProjName,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
2099 : {
2100 0 : sPro.proNumber = EPRJ_LAMBERT_CONFORMAL_CONIC;
2101 0 : sPro.proName = (char*) "Lambert Conformal Conic";
2102 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2103 0 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
2104 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2105 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2106 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2107 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2108 : }
2109 21 : else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP)
2110 : && oSRS.GetProjParm(SRS_PP_SCALE_FACTOR) == 1.0 )
2111 : {
2112 0 : sPro.proNumber = EPRJ_MERCATOR;
2113 0 : sPro.proName = (char*) "Mercator";
2114 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2115 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2116 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2117 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2118 : }
2119 21 : else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) )
2120 : {
2121 0 : sPro.proNumber = EPRJ_MERCATOR_VARIANT_A;
2122 0 : sPro.proName = (char*) "Mercator (Variant A)";
2123 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2124 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2125 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
2126 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2127 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2128 : }
2129 21 : else if( EQUAL(pszProjName,SRS_PT_KROVAK) )
2130 : {
2131 1 : sPro.proNumber = EPRJ_KROVAK;
2132 1 : sPro.proName = (char*) "Krovak";
2133 1 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
2134 1 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
2135 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2136 1 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2137 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2138 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2139 1 : sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1);
2140 :
2141 : // XY plane rotation
2142 1 : sPro.proParams[8] = 0.0;
2143 : // X scale
2144 1 : sPro.proParams[10] = 1.0;
2145 : // Y scale
2146 1 : sPro.proParams[11] = 1.0;
2147 : }
2148 20 : else if( EQUAL(pszProjName,SRS_PT_POLAR_STEREOGRAPHIC) )
2149 : {
2150 0 : sPro.proNumber = EPRJ_POLAR_STEREOGRAPHIC;
2151 0 : sPro.proName = (char*) "Polar Stereographic";
2152 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2153 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2154 : /* hopefully the scale factor is 1.0! */
2155 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2156 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2157 : }
2158 20 : else if( EQUAL(pszProjName,SRS_PT_POLYCONIC) )
2159 : {
2160 1 : sPro.proNumber = EPRJ_POLYCONIC;
2161 1 : sPro.proName = (char*) "Polyconic";
2162 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2163 1 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2164 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2165 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2166 : }
2167 19 : else if( EQUAL(pszProjName,SRS_PT_EQUIDISTANT_CONIC) )
2168 : {
2169 0 : sPro.proNumber = EPRJ_EQUIDISTANT_CONIC;
2170 0 : sPro.proName = (char*) "Equidistant Conic";
2171 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2172 0 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
2173 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2174 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2175 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2176 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2177 0 : sPro.proParams[8] = 1.0;
2178 : }
2179 19 : else if( EQUAL(pszProjName,SRS_PT_TRANSVERSE_MERCATOR) )
2180 : {
2181 1 : sPro.proNumber = EPRJ_TRANSVERSE_MERCATOR;
2182 1 : sPro.proName = (char*) "Transverse Mercator";
2183 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2184 1 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2185 1 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
2186 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2187 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2188 : }
2189 18 : else if( EQUAL(pszProjName,SRS_PT_STEREOGRAPHIC) )
2190 : {
2191 0 : sPro.proNumber = EPRJ_STEREOGRAPHIC_EXTENDED;
2192 0 : sPro.proName = (char*) "Stereographic (Extended)";
2193 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
2194 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2195 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2196 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2197 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2198 : }
2199 18 : else if( EQUAL(pszProjName,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
2200 : {
2201 1 : sPro.proNumber = EPRJ_LAMBERT_AZIMUTHAL_EQUAL_AREA;
2202 1 : sPro.proName = (char*) "Lambert Azimuthal Equal-area";
2203 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2204 1 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2205 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2206 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2207 : }
2208 17 : else if( EQUAL(pszProjName,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
2209 : {
2210 0 : sPro.proNumber = EPRJ_AZIMUTHAL_EQUIDISTANT;
2211 0 : sPro.proName = (char*) "Azimuthal Equidistant";
2212 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2213 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2214 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2215 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2216 : }
2217 17 : else if( EQUAL(pszProjName,SRS_PT_GNOMONIC) )
2218 : {
2219 0 : sPro.proNumber = EPRJ_GNOMONIC;
2220 0 : sPro.proName = (char*) "Gnomonic";
2221 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2222 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2223 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2224 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2225 : }
2226 17 : else if( EQUAL(pszProjName,SRS_PT_ORTHOGRAPHIC) )
2227 : {
2228 0 : sPro.proNumber = EPRJ_ORTHOGRAPHIC;
2229 0 : sPro.proName = (char*) "Orthographic";
2230 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2231 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2232 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2233 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2234 : }
2235 17 : else if( EQUAL(pszProjName,SRS_PT_SINUSOIDAL) )
2236 : {
2237 0 : sPro.proNumber = EPRJ_SINUSOIDAL;
2238 0 : sPro.proName = (char*) "Sinusoidal";
2239 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2240 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2241 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2242 : }
2243 17 : else if( EQUAL(pszProjName,SRS_PT_EQUIRECTANGULAR) )
2244 : {
2245 0 : sPro.proNumber = EPRJ_EQUIRECTANGULAR;
2246 0 : sPro.proName = (char*) "Equirectangular";
2247 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2248 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2249 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2250 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2251 : }
2252 17 : else if( EQUAL(pszProjName,SRS_PT_MILLER_CYLINDRICAL) )
2253 : {
2254 0 : sPro.proNumber = EPRJ_MILLER_CYLINDRICAL;
2255 0 : sPro.proName = (char*) "Miller Cylindrical";
2256 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2257 : /* hopefully the latitude is zero! */
2258 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2259 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2260 : }
2261 17 : else if( EQUAL(pszProjName,SRS_PT_VANDERGRINTEN) )
2262 : {
2263 0 : sPro.proNumber = EPRJ_VANDERGRINTEN;
2264 0 : sPro.proName = (char*) "Van der Grinten";
2265 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2266 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2267 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2268 : }
2269 17 : else if( EQUAL(pszProjName,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
2270 : {
2271 0 : sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR;
2272 0 : sPro.proName = (char*) "Oblique Mercator (Hotine)";
2273 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
2274 0 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
2275 : /* hopefully the rectified grid angle is zero */
2276 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2277 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2278 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2279 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2280 0 : sPro.proParams[12] = 1.0;
2281 : }
2282 17 : else if( EQUAL(pszProjName,"Hotine_Oblique_Mercator_Azimuth_Center") )
2283 : {
2284 1 : sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
2285 1 : sPro.proName = (char*) "Hotine Oblique Mercator Azimuth Center";
2286 1 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
2287 1 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
2288 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2289 1 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2290 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2291 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2292 1 : sPro.proParams[12] = 1.0;
2293 : }
2294 16 : else if( EQUAL(pszProjName,SRS_PT_ROBINSON) )
2295 : {
2296 0 : sPro.proNumber = EPRJ_ROBINSON;
2297 0 : sPro.proName = (char*) "Robinson";
2298 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2299 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2300 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2301 : }
2302 16 : else if( EQUAL(pszProjName,SRS_PT_MOLLWEIDE) )
2303 : {
2304 0 : sPro.proNumber = EPRJ_MOLLWEIDE;
2305 0 : sPro.proName = (char*) "Mollweide";
2306 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2307 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2308 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2309 : }
2310 16 : else if( EQUAL(pszProjName,SRS_PT_ECKERT_I) )
2311 : {
2312 0 : sPro.proNumber = EPRJ_ECKERT_I;
2313 0 : sPro.proName = (char*) "Eckert I";
2314 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2315 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2316 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2317 : }
2318 16 : else if( EQUAL(pszProjName,SRS_PT_ECKERT_II) )
2319 : {
2320 0 : sPro.proNumber = EPRJ_ECKERT_II;
2321 0 : sPro.proName = (char*) "Eckert II";
2322 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2323 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2324 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2325 : }
2326 16 : else if( EQUAL(pszProjName,SRS_PT_ECKERT_III) )
2327 : {
2328 0 : sPro.proNumber = EPRJ_ECKERT_III;
2329 0 : sPro.proName = (char*) "Eckert III";
2330 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2331 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2332 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2333 : }
2334 16 : else if( EQUAL(pszProjName,SRS_PT_ECKERT_IV) )
2335 : {
2336 0 : sPro.proNumber = EPRJ_ECKERT_IV;
2337 0 : sPro.proName = (char*) "Eckert IV";
2338 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2339 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2340 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2341 : }
2342 16 : else if( EQUAL(pszProjName,SRS_PT_ECKERT_V) )
2343 : {
2344 0 : sPro.proNumber = EPRJ_ECKERT_V;
2345 0 : sPro.proName = (char*) "Eckert V";
2346 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2347 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2348 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2349 : }
2350 16 : else if( EQUAL(pszProjName,SRS_PT_ECKERT_VI) )
2351 : {
2352 0 : sPro.proNumber = EPRJ_ECKERT_VI;
2353 0 : sPro.proName = (char*) "Eckert VI";
2354 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2355 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2356 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2357 : }
2358 16 : else if( EQUAL(pszProjName,SRS_PT_GALL_STEREOGRAPHIC) )
2359 : {
2360 0 : sPro.proNumber = EPRJ_GALL_STEREOGRAPHIC;
2361 0 : sPro.proName = (char*) "Gall Stereographic";
2362 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2363 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2364 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2365 : }
2366 16 : else if( EQUAL(pszProjName,SRS_PT_CASSINI_SOLDNER) )
2367 : {
2368 0 : sPro.proNumber = EPRJ_CASSINI;
2369 0 : sPro.proName = (char*) "Cassini";
2370 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2371 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2372 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2373 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2374 : }
2375 16 : else if( EQUAL(pszProjName,SRS_PT_TWO_POINT_EQUIDISTANT) )
2376 : {
2377 0 : sPro.proNumber = EPRJ_TWO_POINT_EQUIDISTANT;
2378 0 : sPro.proName = (char*) "Two_Point_Equidistant";
2379 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2380 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2381 0 : sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
2382 0 : sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
2383 0 : sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
2384 0 : sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
2385 : }
2386 16 : else if( EQUAL(pszProjName,SRS_PT_BONNE) )
2387 : {
2388 0 : sPro.proNumber = EPRJ_BONNE;
2389 0 : sPro.proName = (char*) "Bonne";
2390 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2391 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2392 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2393 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2394 : }
2395 16 : else if( EQUAL(pszProjName,"Loximuthal") )
2396 : {
2397 0 : sPro.proNumber = EPRJ_LOXIMUTHAL;
2398 0 : sPro.proName = (char*) "Loximuthal";
2399 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2400 0 : sPro.proParams[5] = oSRS.GetProjParm("central_parallel")*D2R;
2401 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2402 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2403 : }
2404 16 : else if( EQUAL(pszProjName,"Quartic_Authalic") )
2405 : {
2406 0 : sPro.proNumber = EPRJ_QUARTIC_AUTHALIC;
2407 0 : sPro.proName = (char*) "Quartic Authalic";
2408 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2409 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2410 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2411 : }
2412 16 : else if( EQUAL(pszProjName,"Winkel_I") )
2413 : {
2414 0 : sPro.proNumber = EPRJ_WINKEL_I;
2415 0 : sPro.proName = (char*) "Winkel I";
2416 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2417 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2418 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2419 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2420 : }
2421 16 : else if( EQUAL(pszProjName,"Winkel_II") )
2422 : {
2423 0 : sPro.proNumber = EPRJ_WINKEL_II;
2424 0 : sPro.proName = (char*) "Winkel II";
2425 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2426 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2427 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2428 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2429 : }
2430 16 : else if( EQUAL(pszProjName,"Behrmann") )
2431 : {
2432 0 : sPro.proNumber = EPRJ_BEHRMANN;
2433 0 : sPro.proName = (char*) "Behrmann";
2434 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2435 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2436 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2437 : }
2438 16 : else if( EQUAL(pszProjName,"Equidistant_Cylindrical") )
2439 : {
2440 1 : sPro.proNumber = EPRJ_EQUIDISTANT_CYLINDRICAL;
2441 1 : sPro.proName = (char*) "Equidistant_Cylindrical";
2442 1 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2443 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2444 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2445 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2446 : }
2447 15 : else if( EQUAL(pszProjName, SRS_PT_KROVAK) )
2448 : {
2449 0 : sPro.proNumber = EPRJ_KROVAK;
2450 0 : sPro.proName = (char*) "Krovak";
2451 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
2452 0 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
2453 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
2454 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
2455 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2456 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2457 0 : sPro.proParams[8] = oSRS.GetProjParm("XY_Plane_Rotation", 0.0)*D2R;
2458 0 : sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2459 0 : sPro.proParams[10] = oSRS.GetProjParm("X_Scale", 1.0);
2460 0 : sPro.proParams[11] = oSRS.GetProjParm("Y_Scale", 1.0);
2461 : }
2462 15 : else if( EQUAL(pszProjName, "Double_Stereographic") )
2463 : {
2464 1 : sPro.proNumber = EPRJ_DOUBLE_STEREOGRAPHIC;
2465 1 : sPro.proName = (char*) "Double_Stereographic";
2466 1 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
2467 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2468 1 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
2469 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2470 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2471 : }
2472 14 : else if( EQUAL(pszProjName, "Aitoff") )
2473 : {
2474 0 : sPro.proNumber = EPRJ_AITOFF;
2475 0 : sPro.proName = (char*) "Aitoff";
2476 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2477 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2478 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2479 : }
2480 14 : else if( EQUAL(pszProjName, "Craster_Parabolic") )
2481 : {
2482 0 : sPro.proNumber = EPRJ_CRASTER_PARABOLIC;
2483 0 : sPro.proName = (char*) "Craster_Parabolic";
2484 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2485 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2486 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2487 : }
2488 14 : else if( EQUAL(pszProjName, SRS_PT_CYLINDRICAL_EQUAL_AREA) )
2489 : {
2490 1 : sPro.proNumber = EPRJ_CYLINDRICAL_EQUAL_AREA;
2491 1 : sPro.proName = (char*) "Cylindrical_Equal_Area";
2492 1 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2493 1 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2494 1 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2495 1 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2496 : }
2497 13 : else if( EQUAL(pszProjName, "Flat_Polar_Quartic") )
2498 : {
2499 0 : sPro.proNumber = EPRJ_FLAT_POLAR_QUARTIC;
2500 0 : sPro.proName = (char*) "Flat_Polar_Quartic";
2501 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2502 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2503 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2504 : }
2505 13 : else if( EQUAL(pszProjName, "Times") )
2506 : {
2507 0 : sPro.proNumber = EPRJ_TIMES;
2508 0 : sPro.proName = (char*) "Times";
2509 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2510 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2511 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2512 : }
2513 13 : else if( EQUAL(pszProjName, "Winkel_Tripel") )
2514 : {
2515 0 : sPro.proNumber = EPRJ_WINKEL_TRIPEL;
2516 0 : sPro.proName = (char*) "Winkel_Tripel";
2517 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
2518 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2519 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2520 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2521 : }
2522 13 : else if( EQUAL(pszProjName, "Hammer_Aitoff") )
2523 : {
2524 0 : sPro.proNumber = EPRJ_HAMMER_AITOFF;
2525 0 : sPro.proName = (char*) "Hammer_Aitoff";
2526 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
2527 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2528 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2529 : }
2530 13 : else if( EQUAL(pszProjName, "Vertical_Near_Side_Perspective") )
2531 : {
2532 0 : sPro.proNumber = EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE;
2533 0 : sPro.proName = (char*) "Vertical_Near_Side_Perspective";
2534 0 : sPro.proParams[2] = oSRS.GetProjParm("Height");
2535 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0)*D2R;
2536 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
2537 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2538 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2539 : }
2540 13 : else if( EQUAL(pszProjName, "Hotine_Oblique_Mercator_Azimuth_Center") )
2541 : {
2542 0 : sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
2543 0 : sPro.proName = (char*) "Hotine_Oblique_Mercator_Azimuth_Center";
2544 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
2545 0 : sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH, 45.0)*D2R;
2546 0 : sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0)*D2R;
2547 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
2548 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2549 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2550 : }
2551 13 : else if( EQUAL(pszProjName, "Hotine_Oblique_Mercator_Two_Point_Center") )
2552 : {
2553 0 : sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER;
2554 0 : sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Center";
2555 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
2556 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
2557 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2558 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2559 0 : sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
2560 0 : sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
2561 0 : sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
2562 0 : sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
2563 : }
2564 13 : else if( EQUAL(pszProjName, SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
2565 : {
2566 0 : sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN;
2567 0 : sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Natural_Origin";
2568 0 : sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
2569 0 : sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
2570 0 : sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
2571 0 : sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
2572 0 : sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
2573 0 : sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
2574 0 : sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
2575 0 : sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
2576 : }
2577 13 : else if( EQUAL(pszProjName,"New_Zealand_Map_Grid") )
2578 : {
2579 1 : sPro.proType = EPRJ_EXTERNAL;
2580 1 : sPro.proNumber = 0;
2581 1 : sPro.proExeName = (char*) EPRJ_EXTERNAL_NZMG;
2582 1 : sPro.proName = (char*) "New Zealand Map Grid";
2583 1 : sPro.proZone = 0;
2584 1 : sPro.proParams[0] = 0; // false easting etc not stored in .img it seems
2585 1 : sPro.proParams[1] = 0; // always fixed by definition.
2586 1 : sPro.proParams[2] = 0;
2587 1 : sPro.proParams[3] = 0;
2588 1 : sPro.proParams[4] = 0;
2589 1 : sPro.proParams[5] = 0;
2590 1 : sPro.proParams[6] = 0;
2591 1 : sPro.proParams[7] = 0;
2592 : }
2593 : // Anything we can't map, we store as an ESRI PE_STRING
2594 12 : else if( oSRS.IsProjected() || oSRS.IsGeographic() )
2595 : {
2596 12 : if(!bPEStringStored)
2597 : {
2598 0 : char *pszPEString = NULL;
2599 0 : oSRS.morphToESRI();
2600 0 : oSRS.exportToWkt( &pszPEString );
2601 : // need to transform this into ESRI format.
2602 0 : HFASetPEString( hHFA, pszPEString );
2603 0 : CPLFree( pszPEString );
2604 0 : bPEStringStored = TRUE;
2605 : }
2606 : }
2607 : else
2608 : {
2609 : CPLError( CE_Warning, CPLE_NotSupported,
2610 : "Projection %s not supported for translation to Imagine.",
2611 0 : pszProjName );
2612 : }
2613 :
2614 : /* -------------------------------------------------------------------- */
2615 : /* MapInfo */
2616 : /* -------------------------------------------------------------------- */
2617 92 : const char *pszPROJCS = oSRS.GetAttrValue( "PROJCS" );
2618 :
2619 92 : if( pszPROJCS )
2620 45 : sMapInfo.proName = (char *) pszPROJCS;
2621 82 : else if( bHaveSRS && sPro.proName != NULL )
2622 35 : sMapInfo.proName = sPro.proName;
2623 : else
2624 12 : sMapInfo.proName = (char*) "Unknown";
2625 :
2626 : sMapInfo.upperLeftCenter.x =
2627 92 : adfGeoTransform[0] + adfGeoTransform[1]*0.5;
2628 : sMapInfo.upperLeftCenter.y =
2629 92 : adfGeoTransform[3] + adfGeoTransform[5]*0.5;
2630 :
2631 : sMapInfo.lowerRightCenter.x =
2632 92 : adfGeoTransform[0] + adfGeoTransform[1] * (GetRasterXSize()-0.5);
2633 : sMapInfo.lowerRightCenter.y =
2634 92 : adfGeoTransform[3] + adfGeoTransform[5] * (GetRasterYSize()-0.5);
2635 :
2636 92 : sMapInfo.pixelSize.width = ABS(adfGeoTransform[1]);
2637 92 : sMapInfo.pixelSize.height = ABS(adfGeoTransform[5]);
2638 :
2639 : /* -------------------------------------------------------------------- */
2640 : /* Handle units. Try to match up with a known name. */
2641 : /* -------------------------------------------------------------------- */
2642 92 : sMapInfo.units = (char*) "meters";
2643 :
2644 92 : if( bHaveSRS && oSRS.IsGeographic() )
2645 35 : sMapInfo.units = (char*) "dd";
2646 57 : else if( bHaveSRS && oSRS.GetLinearUnits() != 1.0 )
2647 : {
2648 4 : double dfClosestDiff = 100.0;
2649 4 : int iClosest=-1, iUnit;
2650 4 : char *pszUnitName = NULL;
2651 4 : double dfActualSize = oSRS.GetLinearUnits( &pszUnitName );
2652 :
2653 140 : for( iUnit = 0; apszUnitMap[iUnit] != NULL; iUnit += 2 )
2654 : {
2655 136 : if( fabs(atof(apszUnitMap[iUnit+1]) - dfActualSize) < dfClosestDiff )
2656 : {
2657 14 : iClosest = iUnit;
2658 14 : dfClosestDiff = fabs(atof(apszUnitMap[iUnit+1])-dfActualSize);
2659 : }
2660 : }
2661 :
2662 5 : if( iClosest == -1 || fabs(dfClosestDiff/dfActualSize) > 0.0001 )
2663 : {
2664 : CPLError( CE_Warning, CPLE_NotSupported,
2665 : "Unable to identify Erdas units matching %s/%gm,\n"
2666 : "output units will be wrong.",
2667 1 : pszUnitName, dfActualSize );
2668 : }
2669 : else
2670 3 : sMapInfo.units = (char *) apszUnitMap[iClosest];
2671 :
2672 : /* We need to convert false easting and northing to meters. */
2673 4 : sPro.proParams[6] *= dfActualSize;
2674 4 : sPro.proParams[7] *= dfActualSize;
2675 : }
2676 :
2677 : /* -------------------------------------------------------------------- */
2678 : /* Write out definitions. */
2679 : /* -------------------------------------------------------------------- */
2680 183 : if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
2681 : {
2682 91 : HFASetMapInfo( hHFA, &sMapInfo );
2683 : }
2684 : else
2685 : {
2686 : HFASetGeoTransform( hHFA,
2687 : sMapInfo.proName, sMapInfo.units,
2688 1 : adfGeoTransform );
2689 : }
2690 :
2691 160 : if( bHaveSRS && sPro.proName != NULL)
2692 : {
2693 68 : HFASetProParameters( hHFA, &sPro );
2694 68 : HFASetDatum( hHFA, &sDatum );
2695 :
2696 68 : if( !bPEStringStored )
2697 0 : HFASetPEString( hHFA, "" );
2698 : }
2699 24 : else if( !bPEStringStored )
2700 12 : ClearSR(hHFA);
2701 :
2702 : /* -------------------------------------------------------------------- */
2703 : /* Cleanup */
2704 : /* -------------------------------------------------------------------- */
2705 92 : if( poGeogSRS != NULL )
2706 80 : delete poGeogSRS;
2707 :
2708 92 : return CE_None;
2709 : }
2710 :
2711 : /************************************************************************/
2712 : /* WritePeStringIfNeeded() */
2713 : /************************************************************************/
2714 80 : int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA)
2715 : {
2716 80 : OGRBoolean ret = FALSE;
2717 80 : if(!poSRS || !hHFA)
2718 0 : return ret;
2719 :
2720 80 : const char *pszGEOGCS = poSRS->GetAttrValue( "GEOGCS" );
2721 80 : const char *pszDatum = poSRS->GetAttrValue( "DATUM" );
2722 80 : int gcsNameOffset = 0;
2723 80 : int datumNameOffset = 0;
2724 80 : if(strstr(pszGEOGCS, "GCS_"))
2725 3 : gcsNameOffset = strlen("GCS_");
2726 80 : if(strstr(pszDatum, "D_"))
2727 0 : datumNameOffset = strlen("D_");
2728 :
2729 80 : if(!EQUAL(pszGEOGCS+gcsNameOffset, pszDatum+datumNameOffset))
2730 76 : ret = TRUE;
2731 : else
2732 : {
2733 4 : const char* name = poSRS->GetAttrValue("PRIMEM");
2734 4 : if(name && !EQUAL(name,"Greenwich"))
2735 0 : ret = TRUE;
2736 4 : if(!ret)
2737 : {
2738 4 : OGR_SRSNode * poAUnits = poSRS->GetAttrNode( "GEOGCS|UNIT" );
2739 4 : name = poAUnits->GetChild(0)->GetValue();
2740 4 : if(name && !EQUAL(name,"Degree"))
2741 0 : ret = TRUE;
2742 : }
2743 4 : if(!ret)
2744 : {
2745 4 : name = poSRS->GetAttrValue("UNIT");
2746 4 : if(name)
2747 : {
2748 4 : ret = TRUE;
2749 140 : for(int i=0; apszUnitMap[i] != NULL; i+=2)
2750 136 : if(EQUAL(name, apszUnitMap[i]))
2751 1 : ret = FALSE;
2752 : }
2753 : }
2754 4 : if(!ret)
2755 : {
2756 1 : int nGCS = poSRS->GetEPSGGeogCS();
2757 1 : switch(nGCS)
2758 : {
2759 : case 4326:
2760 1 : if(!EQUAL(pszDatum+datumNameOffset, "WGS_84"))
2761 1 : ret = TRUE;
2762 1 : break;
2763 : case 4322:
2764 0 : if(!EQUAL(pszDatum+datumNameOffset, "WGS_72"))
2765 0 : ret = TRUE;
2766 0 : break;
2767 : case 4267:
2768 0 : if(!EQUAL(pszDatum+datumNameOffset, "North_America_1927"))
2769 0 : ret = TRUE;
2770 0 : break;
2771 : case 4269:
2772 0 : if(!EQUAL(pszDatum+datumNameOffset, "North_America_1983"))
2773 0 : ret = TRUE;
2774 : break;
2775 : }
2776 : }
2777 : }
2778 80 : if(ret)
2779 : {
2780 80 : char *pszPEString = NULL;
2781 80 : poSRS->morphToESRI();
2782 80 : poSRS->exportToWkt( &pszPEString );
2783 80 : HFASetPEString( hHFA, pszPEString );
2784 80 : CPLFree( pszPEString );
2785 : }
2786 :
2787 80 : return ret;
2788 : }
2789 :
2790 : /************************************************************************/
2791 : /* ClearSR() */
2792 : /************************************************************************/
2793 12 : void ClearSR(HFAHandle hHFA)
2794 : {
2795 24 : for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
2796 : {
2797 : HFAEntry *poMIEntry;
2798 12 : if( hHFA->papoBand[iBand]->poNode && (poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection")) != NULL )
2799 : {
2800 0 : poMIEntry->MarkDirty();
2801 0 : poMIEntry->SetIntField( "proType", 0 );
2802 0 : poMIEntry->SetIntField( "proNumber", 0 );
2803 0 : poMIEntry->SetStringField( "proExeName", "");
2804 0 : poMIEntry->SetStringField( "proName", "");
2805 0 : poMIEntry->SetIntField( "proZone", 0 );
2806 0 : poMIEntry->SetDoubleField( "proParams[0]", 0.0 );
2807 0 : poMIEntry->SetDoubleField( "proParams[1]", 0.0 );
2808 0 : poMIEntry->SetDoubleField( "proParams[2]", 0.0 );
2809 0 : poMIEntry->SetDoubleField( "proParams[3]", 0.0 );
2810 0 : poMIEntry->SetDoubleField( "proParams[4]", 0.0 );
2811 0 : poMIEntry->SetDoubleField( "proParams[5]", 0.0 );
2812 0 : poMIEntry->SetDoubleField( "proParams[6]", 0.0 );
2813 0 : poMIEntry->SetDoubleField( "proParams[7]", 0.0 );
2814 0 : poMIEntry->SetDoubleField( "proParams[8]", 0.0 );
2815 0 : poMIEntry->SetDoubleField( "proParams[9]", 0.0 );
2816 0 : poMIEntry->SetDoubleField( "proParams[10]", 0.0 );
2817 0 : poMIEntry->SetDoubleField( "proParams[11]", 0.0 );
2818 0 : poMIEntry->SetDoubleField( "proParams[12]", 0.0 );
2819 0 : poMIEntry->SetDoubleField( "proParams[13]", 0.0 );
2820 0 : poMIEntry->SetDoubleField( "proParams[14]", 0.0 );
2821 0 : poMIEntry->SetStringField( "proSpheroid.sphereName", "" );
2822 0 : poMIEntry->SetDoubleField( "proSpheroid.a", 0.0 );
2823 0 : poMIEntry->SetDoubleField( "proSpheroid.b", 0.0 );
2824 0 : poMIEntry->SetDoubleField( "proSpheroid.eSquared", 0.0 );
2825 0 : poMIEntry->SetDoubleField( "proSpheroid.radius", 0.0 );
2826 0 : HFAEntry* poDatumEntry = poMIEntry->GetNamedChild("Datum");
2827 0 : if( poDatumEntry != NULL )
2828 : {
2829 0 : poDatumEntry->MarkDirty();
2830 0 : poDatumEntry->SetStringField( "datumname", "" );
2831 0 : poDatumEntry->SetIntField( "type", 0 );
2832 0 : poDatumEntry->SetDoubleField( "params[0]", 0.0 );
2833 0 : poDatumEntry->SetDoubleField( "params[1]", 0.0 );
2834 0 : poDatumEntry->SetDoubleField( "params[2]", 0.0 );
2835 0 : poDatumEntry->SetDoubleField( "params[3]", 0.0 );
2836 0 : poDatumEntry->SetDoubleField( "params[4]", 0.0 );
2837 0 : poDatumEntry->SetDoubleField( "params[5]", 0.0 );
2838 0 : poDatumEntry->SetDoubleField( "params[6]", 0.0 );
2839 0 : poDatumEntry->SetStringField( "gridname", "" );
2840 : }
2841 0 : poMIEntry->FlushToDisk();
2842 0 : char* peStr = HFAGetPEString( hHFA );
2843 0 : if( peStr != NULL && strlen(peStr) > 0 )
2844 0 : HFASetPEString( hHFA, "" );
2845 : }
2846 : }
2847 : return;
2848 : }
2849 :
2850 : /************************************************************************/
2851 : /* ESRIToUSGSZone() */
2852 : /* */
2853 : /* Convert ESRI style state plane zones to USGS style state */
2854 : /* plane zones. */
2855 : /************************************************************************/
2856 :
2857 3 : static int ESRIToUSGSZone( int nESRIZone )
2858 :
2859 : {
2860 3 : int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
2861 : int i;
2862 :
2863 3 : if( nESRIZone < 0 )
2864 1 : return ABS(nESRIZone);
2865 :
2866 212 : for( i = 0; i < nPairs; i++ )
2867 : {
2868 212 : if( anUsgsEsriZones[i*2+1] == nESRIZone )
2869 2 : return anUsgsEsriZones[i*2];
2870 : }
2871 :
2872 0 : return 0;
2873 : }
2874 :
2875 : /************************************************************************/
2876 : /* PCSStructToWKT() */
2877 : /* */
2878 : /* Convert the datum, proparameters and mapinfo structures into */
2879 : /* WKT format. */
2880 : /************************************************************************/
2881 :
2882 : char *
2883 39 : HFAPCSStructToWKT( const Eprj_Datum *psDatum,
2884 : const Eprj_ProParameters *psPro,
2885 : const Eprj_MapInfo *psMapInfo,
2886 : HFAEntry *poMapInformation )
2887 :
2888 : {
2889 39 : OGRSpatialReference oSRS;
2890 39 : char *pszNewProj = NULL;
2891 :
2892 : /* -------------------------------------------------------------------- */
2893 : /* General case for Erdas style projections. */
2894 : /* */
2895 : /* We make a particular effort to adapt the mapinfo->proname as */
2896 : /* the PROJCS[] name per #2422. */
2897 : /* -------------------------------------------------------------------- */
2898 :
2899 39 : if( psPro == NULL && psMapInfo != NULL )
2900 : {
2901 0 : oSRS.SetLocalCS( psMapInfo->proName );
2902 : }
2903 :
2904 39 : else if( psPro == NULL )
2905 : {
2906 0 : return NULL;
2907 : }
2908 :
2909 39 : else if( psPro->proType == EPRJ_EXTERNAL )
2910 : {
2911 0 : if( EQUALN(psPro->proExeName,EPRJ_EXTERNAL_NZMG,4) )
2912 : {
2913 : /* -------------------------------------------------------------------- */
2914 : /* handle NZMG which is an external projection see */
2915 : /* http://www.linz.govt.nz/core/surveysystem/geodeticinfo\ */
2916 : /* /datums-projections/projections/nzmg/index.html */
2917 : /* -------------------------------------------------------------------- */
2918 : /* Is there a better way that doesn't require hardcoding of these numbers? */
2919 0 : oSRS.SetNZMG(-41.0,173.0,2510000,6023150);
2920 : }
2921 : else
2922 : {
2923 0 : oSRS.SetLocalCS( psPro->proName );
2924 : }
2925 : }
2926 :
2927 73 : else if( psPro->proNumber != EPRJ_LATLONG
2928 : && psMapInfo != NULL )
2929 : {
2930 34 : oSRS.SetProjCS( psMapInfo->proName );
2931 : }
2932 5 : else if( psPro->proNumber != EPRJ_LATLONG )
2933 : {
2934 5 : oSRS.SetProjCS( psPro->proName );
2935 : }
2936 :
2937 : /* -------------------------------------------------------------------- */
2938 : /* Handle units. It is important to deal with this first so */
2939 : /* that the projection Set methods will automatically do */
2940 : /* translation of linear values (like false easting) to PROJCS */
2941 : /* units from meters. Erdas linear projection values are */
2942 : /* always in meters. */
2943 : /* -------------------------------------------------------------------- */
2944 39 : int iUnitIndex = 0;
2945 :
2946 39 : if( oSRS.IsProjected() || oSRS.IsLocal() )
2947 : {
2948 39 : const char *pszUnits = NULL;
2949 :
2950 39 : if( psMapInfo )
2951 34 : pszUnits = psMapInfo->units;
2952 5 : else if( poMapInformation != NULL )
2953 4 : pszUnits = poMapInformation->GetStringField( "units.string" );
2954 :
2955 39 : if( pszUnits != NULL )
2956 : {
2957 148 : for( iUnitIndex = 0;
2958 74 : apszUnitMap[iUnitIndex] != NULL;
2959 : iUnitIndex += 2 )
2960 : {
2961 74 : if( EQUAL(apszUnitMap[iUnitIndex], pszUnits ) )
2962 38 : break;
2963 : }
2964 :
2965 38 : if( apszUnitMap[iUnitIndex] == NULL )
2966 0 : iUnitIndex = 0;
2967 :
2968 : oSRS.SetLinearUnits( pszUnits,
2969 38 : atof(apszUnitMap[iUnitIndex+1]) );
2970 : }
2971 : else
2972 1 : oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
2973 : }
2974 :
2975 39 : if( psPro == NULL )
2976 : {
2977 0 : if( oSRS.IsLocal() )
2978 : {
2979 0 : if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
2980 0 : return pszNewProj;
2981 : else
2982 : {
2983 0 : pszNewProj = NULL;
2984 0 : return NULL;
2985 : }
2986 : }
2987 : else
2988 0 : return NULL;
2989 : }
2990 :
2991 : /* -------------------------------------------------------------------- */
2992 : /* Try to work out ellipsoid and datum information. */
2993 : /* -------------------------------------------------------------------- */
2994 39 : const char *pszDatumName = psPro->proSpheroid.sphereName;
2995 39 : const char *pszEllipsoidName = psPro->proSpheroid.sphereName;
2996 : double dfInvFlattening;
2997 :
2998 39 : if( psDatum != NULL )
2999 : {
3000 : int i;
3001 :
3002 39 : pszDatumName = psDatum->datumname;
3003 :
3004 : /* Imagine to WKT translation */
3005 96 : for( i = 0; pszDatumName != NULL && apszDatumMap[i] != NULL; i += 2 )
3006 : {
3007 94 : if( EQUAL(pszDatumName,apszDatumMap[i]) )
3008 : {
3009 37 : pszDatumName = apszDatumMap[i+1];
3010 37 : break;
3011 : }
3012 : }
3013 : }
3014 :
3015 39 : if( psPro->proSpheroid.a == 0.0 )
3016 0 : ((Eprj_ProParameters *) psPro)->proSpheroid.a = 6378137.0;
3017 39 : if( psPro->proSpheroid.b == 0.0 )
3018 0 : ((Eprj_ProParameters *) psPro)->proSpheroid.b = 6356752.3;
3019 :
3020 39 : if( fabs(psPro->proSpheroid.b - psPro->proSpheroid.a) < 0.001 )
3021 0 : dfInvFlattening = 0.0; /* special value for sphere. */
3022 : else
3023 39 : dfInvFlattening = 1.0/(1.0-psPro->proSpheroid.b/psPro->proSpheroid.a);
3024 :
3025 : /* -------------------------------------------------------------------- */
3026 : /* Handle different projection methods. */
3027 : /* -------------------------------------------------------------------- */
3028 39 : switch( psPro->proNumber )
3029 : {
3030 : case EPRJ_LATLONG:
3031 0 : break;
3032 :
3033 : case EPRJ_UTM:
3034 : // We change this to unnamed so that SetUTM will set the long
3035 : // UTM description.
3036 25 : oSRS.SetProjCS( "unnamed" );
3037 25 : oSRS.SetUTM( psPro->proZone, psPro->proParams[3] >= 0.0 );
3038 :
3039 : // The PCS name from the above function may be different with the input name.
3040 : // If there is a PCS name in psMapInfo that is different with
3041 : // the one in psPro, just use it as the PCS name. This case happens
3042 : // if the dataset's SR was written by the new GDAL.
3043 25 : if( psMapInfo && strlen(psMapInfo->proName) > 0
3044 : && strlen(psPro->proName) > 0
3045 : && !EQUAL(psMapInfo->proName, psPro->proName) )
3046 7 : oSRS.SetProjCS( psMapInfo->proName );
3047 25 : break;
3048 :
3049 : case EPRJ_STATE_PLANE:
3050 : {
3051 3 : char *pszUnitsName = NULL;
3052 3 : double dfLinearUnits = oSRS.GetLinearUnits( &pszUnitsName );
3053 :
3054 3 : pszUnitsName = CPLStrdup( pszUnitsName );
3055 :
3056 : /* Historically, hfa used esri state plane zone code. Try esri pe string first. */
3057 3 : int zoneCode = ESRIToUSGSZone(psPro->proZone);
3058 : char nad[32];
3059 3 : strcpy(nad, "HARN");
3060 3 : if(psDatum)
3061 3 : strcpy(nad, psDatum->datumname);
3062 : char units[32];
3063 3 : strcpy(units, "meters");
3064 3 : if(psMapInfo)
3065 0 : strcpy(units, psMapInfo->units);
3066 3 : else if(pszUnitsName && strlen(pszUnitsName) > 0)
3067 3 : strcpy(units, pszUnitsName);
3068 3 : int proNu = 0;
3069 3 : if(psPro)
3070 3 : proNu = psPro->proNumber;
3071 3 : if(oSRS.ImportFromESRIStatePlaneWKT(zoneCode, nad, units, proNu) == OGRERR_NONE)
3072 : {
3073 3 : CPLFree( pszUnitsName );
3074 3 : oSRS.morphFromESRI();
3075 3 : oSRS.AutoIdentifyEPSG();
3076 3 : oSRS.Fixup();
3077 3 : if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
3078 3 : return pszNewProj;
3079 : else
3080 0 : return NULL;
3081 : }
3082 :
3083 : /* Set state plane zone. Set NAD83/27 on basis of spheroid */
3084 : oSRS.SetStatePlane( ESRIToUSGSZone(psPro->proZone),
3085 : fabs(psPro->proSpheroid.a - 6378137.0)< 1.0,
3086 0 : pszUnitsName, dfLinearUnits );
3087 :
3088 0 : CPLFree( pszUnitsName );
3089 :
3090 : // Same as the UTM, The following is needed.
3091 0 : if( psMapInfo && strlen(psMapInfo->proName) > 0
3092 : && strlen(psPro->proName) > 0
3093 : && !EQUAL(psMapInfo->proName, psPro->proName) )
3094 0 : oSRS.SetProjCS( psMapInfo->proName );
3095 : }
3096 0 : break;
3097 :
3098 : case EPRJ_ALBERS_CONIC_EQUAL_AREA:
3099 0 : oSRS.SetACEA( psPro->proParams[2]*R2D, psPro->proParams[3]*R2D,
3100 0 : psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3101 0 : psPro->proParams[6], psPro->proParams[7] );
3102 0 : break;
3103 :
3104 : case EPRJ_LAMBERT_CONFORMAL_CONIC:
3105 : // check the possible Wisconsin first
3106 0 : if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
3107 : {
3108 0 : if(oSRS.ImportFromESRIWisconsinWKT("Lambert_Conformal_Conic", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
3109 : {
3110 0 : oSRS.morphFromESRI();
3111 0 : oSRS.AutoIdentifyEPSG();
3112 0 : oSRS.Fixup();
3113 0 : if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
3114 0 : return pszNewProj;
3115 : }
3116 : }
3117 0 : oSRS.SetLCC( psPro->proParams[2]*R2D, psPro->proParams[3]*R2D,
3118 0 : psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3119 0 : psPro->proParams[6], psPro->proParams[7] );
3120 0 : break;
3121 :
3122 : case EPRJ_MERCATOR:
3123 0 : oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3124 : 1.0,
3125 0 : psPro->proParams[6], psPro->proParams[7] );
3126 0 : break;
3127 :
3128 : case EPRJ_POLAR_STEREOGRAPHIC:
3129 0 : oSRS.SetPS( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3130 : 1.0,
3131 0 : psPro->proParams[6], psPro->proParams[7] );
3132 0 : break;
3133 :
3134 : case EPRJ_POLYCONIC:
3135 0 : oSRS.SetPolyconic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3136 0 : psPro->proParams[6], psPro->proParams[7] );
3137 0 : break;
3138 :
3139 : case EPRJ_EQUIDISTANT_CONIC:
3140 : double dfStdParallel2;
3141 :
3142 0 : if( psPro->proParams[8] != 0.0 )
3143 0 : dfStdParallel2 = psPro->proParams[3]*R2D;
3144 : else
3145 0 : dfStdParallel2 = psPro->proParams[2]*R2D;
3146 0 : oSRS.SetEC( psPro->proParams[2]*R2D, dfStdParallel2,
3147 0 : psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3148 0 : psPro->proParams[6], psPro->proParams[7] );
3149 0 : break;
3150 :
3151 : case EPRJ_TRANSVERSE_MERCATOR:
3152 : case EPRJ_GAUSS_KRUGER:
3153 : // check the possible Wisconsin first
3154 11 : if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
3155 : {
3156 0 : if(oSRS.ImportFromESRIWisconsinWKT("Transverse_Mercator", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
3157 : {
3158 0 : oSRS.morphFromESRI();
3159 0 : oSRS.AutoIdentifyEPSG();
3160 0 : oSRS.Fixup();
3161 0 : if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
3162 0 : return pszNewProj;
3163 : }
3164 : }
3165 22 : oSRS.SetTM( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3166 : psPro->proParams[2],
3167 33 : psPro->proParams[6], psPro->proParams[7] );
3168 11 : break;
3169 :
3170 : case EPRJ_STEREOGRAPHIC:
3171 0 : oSRS.SetStereographic( psPro->proParams[5]*R2D,psPro->proParams[4]*R2D,
3172 : 1.0,
3173 0 : psPro->proParams[6], psPro->proParams[7] );
3174 0 : break;
3175 :
3176 : case EPRJ_LAMBERT_AZIMUTHAL_EQUAL_AREA:
3177 0 : oSRS.SetLAEA( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3178 0 : psPro->proParams[6], psPro->proParams[7] );
3179 0 : break;
3180 :
3181 : case EPRJ_AZIMUTHAL_EQUIDISTANT:
3182 0 : oSRS.SetAE( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3183 0 : psPro->proParams[6], psPro->proParams[7] );
3184 0 : break;
3185 :
3186 : case EPRJ_GNOMONIC:
3187 0 : oSRS.SetGnomonic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3188 0 : psPro->proParams[6], psPro->proParams[7] );
3189 0 : break;
3190 :
3191 : case EPRJ_ORTHOGRAPHIC:
3192 0 : oSRS.SetOrthographic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3193 0 : psPro->proParams[6], psPro->proParams[7] );
3194 0 : break;
3195 :
3196 : case EPRJ_SINUSOIDAL:
3197 0 : oSRS.SetSinusoidal( psPro->proParams[4]*R2D,
3198 0 : psPro->proParams[6], psPro->proParams[7] );
3199 0 : break;
3200 :
3201 : case EPRJ_PLATE_CARREE:
3202 : case EPRJ_EQUIRECTANGULAR:
3203 : oSRS.SetEquirectangular2( 0.0,
3204 0 : psPro->proParams[4]*R2D,
3205 0 : psPro->proParams[5]*R2D,
3206 0 : psPro->proParams[6], psPro->proParams[7] );
3207 0 : break;
3208 :
3209 : case EPRJ_EQUIDISTANT_CYLINDRICAL:
3210 : oSRS.SetEquirectangular2( 0.0,
3211 0 : psPro->proParams[4]*R2D,
3212 0 : psPro->proParams[2]*R2D,
3213 0 : psPro->proParams[6], psPro->proParams[7] );
3214 0 : break;
3215 :
3216 : case EPRJ_MILLER_CYLINDRICAL:
3217 0 : oSRS.SetMC( 0.0, psPro->proParams[4]*R2D,
3218 0 : psPro->proParams[6], psPro->proParams[7] );
3219 0 : break;
3220 :
3221 : case EPRJ_VANDERGRINTEN:
3222 0 : oSRS.SetVDG( psPro->proParams[4]*R2D,
3223 0 : psPro->proParams[6], psPro->proParams[7] );
3224 0 : break;
3225 :
3226 : case EPRJ_HOTINE_OBLIQUE_MERCATOR:
3227 0 : if( psPro->proParams[12] > 0.0 )
3228 0 : oSRS.SetHOM( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3229 0 : psPro->proParams[3]*R2D, 0.0,
3230 : psPro->proParams[2],
3231 0 : psPro->proParams[6], psPro->proParams[7] );
3232 0 : break;
3233 :
3234 : case EPRJ_ROBINSON:
3235 0 : oSRS.SetRobinson( psPro->proParams[4]*R2D,
3236 0 : psPro->proParams[6], psPro->proParams[7] );
3237 0 : break;
3238 :
3239 : case EPRJ_MOLLWEIDE:
3240 0 : oSRS.SetMollweide( psPro->proParams[4]*R2D,
3241 0 : psPro->proParams[6], psPro->proParams[7] );
3242 0 : break;
3243 :
3244 : case EPRJ_GALL_STEREOGRAPHIC:
3245 0 : oSRS.SetGS( psPro->proParams[4]*R2D,
3246 0 : psPro->proParams[6], psPro->proParams[7] );
3247 0 : break;
3248 :
3249 : case EPRJ_ECKERT_I:
3250 0 : oSRS.SetEckert( 1, psPro->proParams[4]*R2D,
3251 0 : psPro->proParams[6], psPro->proParams[7] );
3252 0 : break;
3253 :
3254 : case EPRJ_ECKERT_II:
3255 0 : oSRS.SetEckert( 2, psPro->proParams[4]*R2D,
3256 0 : psPro->proParams[6], psPro->proParams[7] );
3257 0 : break;
3258 :
3259 : case EPRJ_ECKERT_III:
3260 0 : oSRS.SetEckert( 3, psPro->proParams[4]*R2D,
3261 0 : psPro->proParams[6], psPro->proParams[7] );
3262 0 : break;
3263 :
3264 : case EPRJ_ECKERT_IV:
3265 0 : oSRS.SetEckert( 4, psPro->proParams[4]*R2D,
3266 0 : psPro->proParams[6], psPro->proParams[7] );
3267 0 : break;
3268 :
3269 : case EPRJ_ECKERT_V:
3270 0 : oSRS.SetEckert( 5, psPro->proParams[4]*R2D,
3271 0 : psPro->proParams[6], psPro->proParams[7] );
3272 0 : break;
3273 :
3274 : case EPRJ_ECKERT_VI:
3275 0 : oSRS.SetEckert( 6, psPro->proParams[4]*R2D,
3276 0 : psPro->proParams[6], psPro->proParams[7] );
3277 0 : break;
3278 :
3279 : case EPRJ_CASSINI:
3280 0 : oSRS.SetCS( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3281 0 : psPro->proParams[6], psPro->proParams[7] );
3282 0 : break;
3283 :
3284 : case EPRJ_TWO_POINT_EQUIDISTANT:
3285 0 : oSRS.SetTPED( psPro->proParams[9] * R2D,
3286 0 : psPro->proParams[8] * R2D,
3287 0 : psPro->proParams[11] * R2D,
3288 0 : psPro->proParams[10] * R2D,
3289 0 : psPro->proParams[6], psPro->proParams[7] );
3290 0 : break;
3291 :
3292 : case EPRJ_STEREOGRAPHIC_EXTENDED:
3293 0 : oSRS.SetStereographic( psPro->proParams[5]*R2D,psPro->proParams[4]*R2D,
3294 : psPro->proParams[2],
3295 0 : psPro->proParams[6], psPro->proParams[7] );
3296 0 : break;
3297 :
3298 : case EPRJ_BONNE:
3299 0 : oSRS.SetBonne( psPro->proParams[2]*R2D, psPro->proParams[4]*R2D,
3300 0 : psPro->proParams[6], psPro->proParams[7] );
3301 0 : break;
3302 :
3303 : case EPRJ_LOXIMUTHAL:
3304 : {
3305 0 : oSRS.SetProjection( "Loximuthal" );
3306 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3307 0 : psPro->proParams[4] * R2D );
3308 : oSRS.SetNormProjParm( "central_parallel",
3309 0 : psPro->proParams[5] * R2D );
3310 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3311 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3312 : }
3313 0 : break;
3314 :
3315 : case EPRJ_QUARTIC_AUTHALIC:
3316 : {
3317 0 : oSRS.SetProjection( "Quartic_Authalic" );
3318 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3319 0 : psPro->proParams[4] * R2D );
3320 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3321 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3322 : }
3323 0 : break;
3324 :
3325 : case EPRJ_WINKEL_I:
3326 : {
3327 0 : oSRS.SetProjection( "Winkel_I" );
3328 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3329 0 : psPro->proParams[4] * R2D );
3330 : oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
3331 0 : psPro->proParams[2] * R2D );
3332 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3333 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3334 : }
3335 0 : break;
3336 :
3337 : case EPRJ_WINKEL_II:
3338 : {
3339 0 : oSRS.SetProjection( "Winkel_II" );
3340 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3341 0 : psPro->proParams[4] * R2D );
3342 : oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
3343 0 : psPro->proParams[2] * R2D );
3344 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3345 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3346 : }
3347 0 : break;
3348 :
3349 : case EPRJ_BEHRMANN:
3350 : {
3351 0 : oSRS.SetProjection( "Behrmann" );
3352 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3353 0 : psPro->proParams[4] * R2D );
3354 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3355 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3356 : }
3357 0 : break;
3358 :
3359 : case EPRJ_KROVAK:
3360 0 : oSRS.SetKrovak( psPro->proParams[4]*R2D, psPro->proParams[5]*R2D,
3361 0 : psPro->proParams[3]*R2D, psPro->proParams[9]*R2D,
3362 : psPro->proParams[2],
3363 0 : psPro->proParams[6], psPro->proParams[7] );
3364 0 : break;
3365 :
3366 : case EPRJ_DOUBLE_STEREOGRAPHIC:
3367 : {
3368 0 : oSRS.SetProjection( "Double_Stereographic" );
3369 : oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN,
3370 0 : psPro->proParams[5] * R2D );
3371 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3372 0 : psPro->proParams[4] * R2D );
3373 0 : oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR, psPro->proParams[2] );
3374 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3375 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3376 : }
3377 0 : break;
3378 :
3379 : case EPRJ_AITOFF:
3380 : {
3381 0 : oSRS.SetProjection( "Aitoff" );
3382 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3383 0 : psPro->proParams[4] * R2D );
3384 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3385 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3386 : }
3387 0 : break;
3388 :
3389 : case EPRJ_CRASTER_PARABOLIC:
3390 : {
3391 0 : oSRS.SetProjection( "Craster_Parabolic" );
3392 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3393 0 : psPro->proParams[4] * R2D );
3394 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3395 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3396 : }
3397 0 : break;
3398 :
3399 : case EPRJ_CYLINDRICAL_EQUAL_AREA:
3400 0 : oSRS.SetCEA(psPro->proParams[2] * R2D, psPro->proParams[4] * R2D,
3401 0 : psPro->proParams[6], psPro->proParams[7]);
3402 0 : break;
3403 :
3404 : case EPRJ_FLAT_POLAR_QUARTIC:
3405 : {
3406 0 : oSRS.SetProjection( "Flat_Polar_Quartic" );
3407 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3408 0 : psPro->proParams[4] * R2D );
3409 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3410 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3411 : }
3412 0 : break;
3413 :
3414 : case EPRJ_TIMES:
3415 : {
3416 0 : oSRS.SetProjection( "Times" );
3417 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3418 0 : psPro->proParams[4] * R2D );
3419 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3420 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3421 : }
3422 0 : break;
3423 :
3424 : case EPRJ_WINKEL_TRIPEL:
3425 : {
3426 0 : oSRS.SetProjection( "Winkel_Tripel" );
3427 : oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
3428 0 : psPro->proParams[2] * R2D );
3429 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3430 0 : psPro->proParams[4] * R2D );
3431 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3432 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3433 : }
3434 0 : break;
3435 :
3436 : case EPRJ_HAMMER_AITOFF:
3437 : {
3438 0 : oSRS.SetProjection( "Hammer_Aitoff" );
3439 : oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
3440 0 : psPro->proParams[4] * R2D );
3441 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3442 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3443 : }
3444 0 : break;
3445 :
3446 : case EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE:
3447 : {
3448 0 : oSRS.SetProjection( "Vertical_Near_Side_Perspective" );
3449 : oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
3450 0 : psPro->proParams[5] * R2D );
3451 : oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,
3452 0 : psPro->proParams[4] * R2D );
3453 : oSRS.SetNormProjParm( "height",
3454 0 : psPro->proParams[2] );
3455 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3456 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3457 : }
3458 0 : break;
3459 :
3460 : case EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER:
3461 : {
3462 0 : oSRS.SetProjection( "Hotine_Oblique_Mercator_Azimuth_Center" );
3463 : oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
3464 0 : psPro->proParams[5] * R2D );
3465 : oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,
3466 0 : psPro->proParams[4] * R2D );
3467 : oSRS.SetNormProjParm( SRS_PP_AZIMUTH,
3468 0 : psPro->proParams[3] * R2D );
3469 : oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR,
3470 0 : psPro->proParams[2] );
3471 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3472 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3473 : }
3474 0 : break;
3475 :
3476 : case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER:
3477 : {
3478 0 : oSRS.SetProjection( "Hotine_Oblique_Mercator_Twp_Point_Center" );
3479 : oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
3480 0 : psPro->proParams[5] * R2D );
3481 : oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_1ST_POINT,
3482 0 : psPro->proParams[9] * R2D );
3483 : oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_1ST_POINT,
3484 0 : psPro->proParams[8] * R2D );
3485 : oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_2ND_POINT,
3486 0 : psPro->proParams[11] * R2D );
3487 : oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_2ND_POINT,
3488 0 : psPro->proParams[10] * R2D );
3489 : oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR,
3490 0 : psPro->proParams[2] );
3491 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
3492 0 : oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
3493 : }
3494 0 : break;
3495 :
3496 : case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN:
3497 0 : oSRS.SetHOM2PNO( psPro->proParams[5] * R2D,
3498 0 : psPro->proParams[8] * R2D,
3499 0 : psPro->proParams[9] * R2D,
3500 0 : psPro->proParams[10] * R2D,
3501 0 : psPro->proParams[11] * R2D,
3502 : psPro->proParams[2],
3503 0 : psPro->proParams[6], psPro->proParams[7] );
3504 0 : break;
3505 :
3506 : case EPRJ_LAMBERT_CONFORMAL_CONIC_1SP:
3507 0 : oSRS.SetLCC1SP( psPro->proParams[3]*R2D, psPro->proParams[2]*R2D,
3508 : psPro->proParams[4],
3509 0 : psPro->proParams[5], psPro->proParams[6] );
3510 0 : break;
3511 :
3512 : case EPRJ_MERCATOR_VARIANT_A:
3513 0 : oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3514 : psPro->proParams[2],
3515 0 : psPro->proParams[6], psPro->proParams[7] );
3516 0 : break;
3517 :
3518 : case EPRJ_PSEUDO_MERCATOR: // likely this is google mercator?
3519 0 : oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
3520 : 1.0,
3521 0 : psPro->proParams[6], psPro->proParams[7] );
3522 0 : break;
3523 :
3524 : default:
3525 0 : if( oSRS.IsProjected() )
3526 0 : oSRS.GetRoot()->SetValue( "LOCAL_CS" );
3527 : else
3528 0 : oSRS.SetLocalCS( psPro->proName );
3529 : break;
3530 : }
3531 :
3532 : /* -------------------------------------------------------------------- */
3533 : /* Try and set the GeogCS information. */
3534 : /* -------------------------------------------------------------------- */
3535 36 : if( oSRS.GetAttrNode("GEOGCS") == NULL
3536 : && oSRS.GetAttrNode("LOCAL_CS") == NULL )
3537 : {
3538 36 : if( pszDatumName == NULL)
3539 : oSRS.SetGeogCS( pszDatumName, pszDatumName, pszEllipsoidName,
3540 0 : psPro->proSpheroid.a, dfInvFlattening );
3541 36 : else if( EQUAL(pszDatumName,"WGS 84")
3542 : || EQUAL(pszDatumName,"WGS_1984") )
3543 0 : oSRS.SetWellKnownGeogCS( "WGS84" );
3544 61 : else if( strstr(pszDatumName,"NAD27") != NULL
3545 : || EQUAL(pszDatumName,"North_American_Datum_1927") )
3546 25 : oSRS.SetWellKnownGeogCS( "NAD27" );
3547 11 : else if( strstr(pszDatumName,"NAD83") != NULL
3548 : || EQUAL(pszDatumName,"North_American_Datum_1983"))
3549 0 : oSRS.SetWellKnownGeogCS( "NAD83" );
3550 : else
3551 : oSRS.SetGeogCS( pszDatumName, pszDatumName, pszEllipsoidName,
3552 11 : psPro->proSpheroid.a, dfInvFlattening );
3553 :
3554 36 : if( psDatum != NULL && psDatum->type == EPRJ_DATUM_PARAMETRIC )
3555 : {
3556 : oSRS.SetTOWGS84( psDatum->params[0],
3557 : psDatum->params[1],
3558 : psDatum->params[2],
3559 : psDatum->params[3],
3560 : psDatum->params[4],
3561 : psDatum->params[5],
3562 13 : psDatum->params[6] );
3563 : }
3564 : }
3565 :
3566 : /* -------------------------------------------------------------------- */
3567 : /* Try to insert authority information if possible. Fixup any */
3568 : /* ordering oddities. */
3569 : /* -------------------------------------------------------------------- */
3570 36 : oSRS.AutoIdentifyEPSG();
3571 36 : oSRS.Fixup();
3572 :
3573 : /* -------------------------------------------------------------------- */
3574 : /* Get the WKT representation of the coordinate system. */
3575 : /* -------------------------------------------------------------------- */
3576 36 : if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
3577 36 : return pszNewProj;
3578 : else
3579 : {
3580 0 : return NULL;
3581 0 : }
3582 : }
3583 :
3584 : /************************************************************************/
3585 : /* ReadProjection() */
3586 : /************************************************************************/
3587 :
3588 376 : CPLErr HFADataset::ReadProjection()
3589 :
3590 : {
3591 : const Eprj_Datum *psDatum;
3592 : const Eprj_ProParameters *psPro;
3593 : const Eprj_MapInfo *psMapInfo;
3594 376 : OGRSpatialReference oSRS;
3595 : char *pszPE_COORDSYS;
3596 :
3597 : /* -------------------------------------------------------------------- */
3598 : /* Special logic for PE string in ProjectionX node. */
3599 : /* -------------------------------------------------------------------- */
3600 376 : pszPE_COORDSYS = HFAGetPEString( hHFA );
3601 376 : if( pszPE_COORDSYS != NULL
3602 : && strlen(pszPE_COORDSYS) > 0
3603 : && oSRS.SetFromUserInput( pszPE_COORDSYS ) == OGRERR_NONE )
3604 : {
3605 100 : CPLFree( pszPE_COORDSYS );
3606 :
3607 100 : oSRS.morphFromESRI();
3608 100 : oSRS.Fixup();
3609 :
3610 100 : CPLFree( pszProjection );
3611 100 : pszProjection = NULL;
3612 100 : oSRS.exportToWkt( &pszProjection );
3613 :
3614 100 : return CE_None;
3615 : }
3616 :
3617 276 : CPLFree( pszPE_COORDSYS );
3618 :
3619 : /* -------------------------------------------------------------------- */
3620 : /* General case for Erdas style projections. */
3621 : /* */
3622 : /* We make a particular effort to adapt the mapinfo->proname as */
3623 : /* the PROJCS[] name per #2422. */
3624 : /* -------------------------------------------------------------------- */
3625 276 : psDatum = HFAGetDatum( hHFA );
3626 276 : psPro = HFAGetProParameters( hHFA );
3627 276 : psMapInfo = HFAGetMapInfo( hHFA );
3628 :
3629 276 : HFAEntry *poMapInformation = NULL;
3630 276 : if( psMapInfo == NULL )
3631 : {
3632 214 : HFABand *poBand = hHFA->papoBand[0];
3633 214 : poMapInformation = poBand->poNode->GetNamedChild("MapInformation");
3634 : }
3635 :
3636 276 : CPLFree( pszProjection );
3637 :
3638 276 : if( !psDatum || !psPro ||
3639 : (psMapInfo == NULL && poMapInformation == NULL) ||
3640 : ((strlen(psDatum->datumname) == 0 || EQUAL(psDatum->datumname, "Unknown")) &&
3641 : (strlen(psPro->proName) == 0 || EQUAL(psPro->proName, "Unknown")) &&
3642 : (psMapInfo && (strlen(psMapInfo->proName) == 0 || EQUAL(psMapInfo->proName, "Unknown"))) &&
3643 : psPro->proZone == 0) )
3644 : {
3645 238 : pszProjection = CPLStrdup("");
3646 238 : return CE_None;
3647 : }
3648 :
3649 : pszProjection = HFAPCSStructToWKT( psDatum, psPro, psMapInfo,
3650 38 : poMapInformation );
3651 :
3652 38 : if( pszProjection != NULL )
3653 38 : return CE_None;
3654 : else
3655 : {
3656 0 : pszProjection = CPLStrdup("");
3657 0 : return CE_Failure;
3658 0 : }
3659 : }
3660 :
3661 : /************************************************************************/
3662 : /* IBuildOverviews() */
3663 : /************************************************************************/
3664 :
3665 8 : CPLErr HFADataset::IBuildOverviews( const char *pszResampling,
3666 : int nOverviews, int *panOverviewList,
3667 : int nListBands, int *panBandList,
3668 : GDALProgressFunc pfnProgress,
3669 : void * pProgressData )
3670 :
3671 : {
3672 : int i;
3673 :
3674 8 : if( GetAccess() == GA_ReadOnly )
3675 : {
3676 0 : for( i = 0; i < nListBands; i++ )
3677 : {
3678 0 : if (HFAGetOverviewCount(hHFA, panBandList[i]) > 0)
3679 : {
3680 : CPLError(CE_Failure, CPLE_NotSupported,
3681 0 : "Cannot add external overviews when there are already internal overviews");
3682 0 : return CE_Failure;
3683 : }
3684 : }
3685 :
3686 : return GDALDataset::IBuildOverviews( pszResampling,
3687 : nOverviews, panOverviewList,
3688 : nListBands, panBandList,
3689 0 : pfnProgress, pProgressData );
3690 : }
3691 :
3692 16 : for( i = 0; i < nListBands; i++ )
3693 : {
3694 : CPLErr eErr;
3695 : GDALRasterBand *poBand;
3696 :
3697 : void* pScaledProgressData = GDALCreateScaledProgress(
3698 : i * 1.0 / nListBands, (i + 1) * 1.0 / nListBands,
3699 8 : pfnProgress, pProgressData);
3700 :
3701 8 : poBand = GetRasterBand( panBandList[i] );
3702 : eErr =
3703 : poBand->BuildOverviews( pszResampling, nOverviews, panOverviewList,
3704 8 : GDALScaledProgress, pScaledProgressData );
3705 :
3706 8 : GDALDestroyScaledProgress(pScaledProgressData);
3707 :
3708 8 : if( eErr != CE_None )
3709 0 : return eErr;
3710 : }
3711 :
3712 8 : return CE_None;
3713 : }
3714 :
3715 : /************************************************************************/
3716 : /* Identify() */
3717 : /************************************************************************/
3718 :
3719 13280 : int HFADataset::Identify( GDALOpenInfo * poOpenInfo )
3720 :
3721 : {
3722 : /* -------------------------------------------------------------------- */
3723 : /* Verify that this is a HFA file. */
3724 : /* -------------------------------------------------------------------- */
3725 13280 : if( poOpenInfo->nHeaderBytes < 15
3726 : || !EQUALN((char *) poOpenInfo->pabyHeader,"EHFA_HEADER_TAG",15) )
3727 12900 : return FALSE;
3728 : else
3729 380 : return TRUE;
3730 : }
3731 :
3732 : /************************************************************************/
3733 : /* Open() */
3734 : /************************************************************************/
3735 :
3736 4000 : GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
3737 :
3738 : {
3739 : HFAHandle hHFA;
3740 : int i;
3741 :
3742 : /* -------------------------------------------------------------------- */
3743 : /* Verify that this is a HFA file. */
3744 : /* -------------------------------------------------------------------- */
3745 4000 : if( !Identify( poOpenInfo ) )
3746 3621 : return NULL;
3747 :
3748 : /* -------------------------------------------------------------------- */
3749 : /* Open the file. */
3750 : /* -------------------------------------------------------------------- */
3751 379 : if( poOpenInfo->eAccess == GA_Update )
3752 136 : hHFA = HFAOpen( poOpenInfo->pszFilename, "r+" );
3753 : else
3754 243 : hHFA = HFAOpen( poOpenInfo->pszFilename, "r" );
3755 :
3756 379 : if( hHFA == NULL )
3757 0 : return NULL;
3758 :
3759 : /* -------------------------------------------------------------------- */
3760 : /* Create a corresponding GDALDataset. */
3761 : /* -------------------------------------------------------------------- */
3762 : HFADataset *poDS;
3763 :
3764 379 : poDS = new HFADataset();
3765 :
3766 379 : poDS->hHFA = hHFA;
3767 379 : poDS->eAccess = poOpenInfo->eAccess;
3768 :
3769 : /* -------------------------------------------------------------------- */
3770 : /* Establish raster info. */
3771 : /* -------------------------------------------------------------------- */
3772 : HFAGetRasterInfo( hHFA, &poDS->nRasterXSize, &poDS->nRasterYSize,
3773 379 : &poDS->nBands );
3774 :
3775 379 : if( poDS->nBands == 0 )
3776 : {
3777 3 : delete poDS;
3778 : CPLError( CE_Failure, CPLE_AppDefined,
3779 : "Unable to open %s, it has zero usable bands.",
3780 3 : poOpenInfo->pszFilename );
3781 3 : return NULL;
3782 : }
3783 :
3784 376 : if( poDS->nRasterXSize == 0 || poDS->nRasterYSize == 0 )
3785 : {
3786 0 : delete poDS;
3787 : CPLError( CE_Failure, CPLE_AppDefined,
3788 : "Unable to open %s, it has no pixels.",
3789 0 : poOpenInfo->pszFilename );
3790 0 : return NULL;
3791 : }
3792 :
3793 : /* -------------------------------------------------------------------- */
3794 : /* Get geotransform, or if that fails, try to find XForms to */
3795 : /* build gcps, and metadata. */
3796 : /* -------------------------------------------------------------------- */
3797 376 : if( !HFAGetGeoTransform( hHFA, poDS->adfGeoTransform ) )
3798 : {
3799 212 : Efga_Polynomial *pasPolyListForward = NULL;
3800 212 : Efga_Polynomial *pasPolyListReverse = NULL;
3801 : int nStepCount =
3802 : HFAReadXFormStack( hHFA, &pasPolyListForward,
3803 212 : &pasPolyListReverse );
3804 :
3805 212 : if( nStepCount > 0 )
3806 : {
3807 : poDS->UseXFormStack( nStepCount,
3808 : pasPolyListForward,
3809 1 : pasPolyListReverse );
3810 1 : CPLFree( pasPolyListForward );
3811 1 : CPLFree( pasPolyListReverse );
3812 : }
3813 : }
3814 :
3815 : /* -------------------------------------------------------------------- */
3816 : /* Get the projection. */
3817 : /* -------------------------------------------------------------------- */
3818 376 : poDS->ReadProjection();
3819 :
3820 : /* -------------------------------------------------------------------- */
3821 : /* Read the camera model as metadata, if present. */
3822 : /* -------------------------------------------------------------------- */
3823 376 : char **papszCM = HFAReadCameraModel( hHFA );
3824 :
3825 376 : if( papszCM != NULL )
3826 : {
3827 1 : poDS->SetMetadata( papszCM, "CAMERA_MODEL" );
3828 1 : CSLDestroy( papszCM );
3829 : }
3830 :
3831 : /* -------------------------------------------------------------------- */
3832 : /* Create band information objects. */
3833 : /* -------------------------------------------------------------------- */
3834 1652 : for( i = 0; i < poDS->nBands; i++ )
3835 : {
3836 450 : poDS->SetBand( i+1, new HFARasterBand( poDS, i+1, -1 ) );
3837 : }
3838 :
3839 : /* -------------------------------------------------------------------- */
3840 : /* Collect GDAL custom Metadata, and "auxilary" metadata from */
3841 : /* well known HFA structures for the bands. We defer this till */
3842 : /* now to ensure that the bands are properly setup before */
3843 : /* interacting with PAM. */
3844 : /* -------------------------------------------------------------------- */
3845 826 : for( i = 0; i < poDS->nBands; i++ )
3846 : {
3847 450 : HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
3848 :
3849 450 : char **papszMD = HFAGetMetadata( hHFA, i+1 );
3850 450 : if( papszMD != NULL )
3851 : {
3852 7 : poBand->SetMetadata( papszMD );
3853 7 : CSLDestroy( papszMD );
3854 : }
3855 :
3856 450 : poBand->ReadAuxMetadata();
3857 450 : poBand->ReadHistogramMetadata();
3858 : }
3859 :
3860 : /* -------------------------------------------------------------------- */
3861 : /* Check for GDAL style metadata. */
3862 : /* -------------------------------------------------------------------- */
3863 376 : char **papszMD = HFAGetMetadata( hHFA, 0 );
3864 376 : if( papszMD != NULL )
3865 : {
3866 78 : poDS->SetMetadata( papszMD );
3867 78 : CSLDestroy( papszMD );
3868 : }
3869 :
3870 : /* -------------------------------------------------------------------- */
3871 : /* Check for dependent dataset value. */
3872 : /* -------------------------------------------------------------------- */
3873 376 : HFAInfo_t *psInfo = (HFAInfo_t *) hHFA;
3874 376 : HFAEntry *poEntry = psInfo->poRoot->GetNamedChild("DependentFile");
3875 376 : if( poEntry != NULL )
3876 : {
3877 : poDS->SetMetadataItem( "HFA_DEPENDENT_FILE",
3878 : poEntry->GetStringField( "dependent.string" ),
3879 16 : "HFA" );
3880 : }
3881 :
3882 : /* -------------------------------------------------------------------- */
3883 : /* Initialize any PAM information. */
3884 : /* -------------------------------------------------------------------- */
3885 376 : poDS->SetDescription( poOpenInfo->pszFilename );
3886 376 : poDS->TryLoadXML();
3887 :
3888 : /* -------------------------------------------------------------------- */
3889 : /* Check for external overviews. */
3890 : /* -------------------------------------------------------------------- */
3891 376 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
3892 :
3893 : /* -------------------------------------------------------------------- */
3894 : /* Clear dirty metadata flags. */
3895 : /* -------------------------------------------------------------------- */
3896 826 : for( i = 0; i < poDS->nBands; i++ )
3897 : {
3898 450 : HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
3899 450 : poBand->bMetadataDirty = FALSE;
3900 : }
3901 376 : poDS->bMetadataDirty = FALSE;
3902 :
3903 376 : return( poDS );
3904 : }
3905 :
3906 : /************************************************************************/
3907 : /* GetProjectionRef() */
3908 : /************************************************************************/
3909 :
3910 122 : const char *HFADataset::GetProjectionRef()
3911 :
3912 : {
3913 122 : return pszProjection;
3914 : }
3915 :
3916 : /************************************************************************/
3917 : /* SetProjection() */
3918 : /************************************************************************/
3919 :
3920 80 : CPLErr HFADataset::SetProjection( const char * pszNewProjection )
3921 :
3922 : {
3923 80 : CPLFree( pszProjection );
3924 80 : pszProjection = CPLStrdup( pszNewProjection );
3925 80 : bGeoDirty = TRUE;
3926 :
3927 80 : return CE_None;
3928 : }
3929 :
3930 : /************************************************************************/
3931 : /* SetMetadata() */
3932 : /************************************************************************/
3933 :
3934 122 : CPLErr HFADataset::SetMetadata( char **papszMDIn, const char *pszDomain )
3935 :
3936 : {
3937 122 : bMetadataDirty = TRUE;
3938 :
3939 122 : return GDALPamDataset::SetMetadata( papszMDIn, pszDomain );
3940 : }
3941 :
3942 : /************************************************************************/
3943 : /* SetMetadata() */
3944 : /************************************************************************/
3945 :
3946 16 : CPLErr HFADataset::SetMetadataItem( const char *pszTag, const char *pszValue,
3947 : const char *pszDomain )
3948 :
3949 : {
3950 16 : bMetadataDirty = TRUE;
3951 :
3952 16 : return GDALPamDataset::SetMetadataItem( pszTag, pszValue, pszDomain );
3953 : }
3954 :
3955 : /************************************************************************/
3956 : /* GetGeoTransform() */
3957 : /************************************************************************/
3958 :
3959 104 : CPLErr HFADataset::GetGeoTransform( double * padfTransform )
3960 :
3961 : {
3962 119 : if( adfGeoTransform[0] != 0.0
3963 3 : || adfGeoTransform[1] != 1.0
3964 3 : || adfGeoTransform[2] != 0.0
3965 3 : || adfGeoTransform[3] != 0.0
3966 3 : || adfGeoTransform[4] != 0.0
3967 3 : || adfGeoTransform[5] != 1.0 )
3968 : {
3969 101 : memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
3970 101 : return CE_None;
3971 : }
3972 : else
3973 3 : return GDALPamDataset::GetGeoTransform( padfTransform );
3974 : }
3975 :
3976 : /************************************************************************/
3977 : /* SetGeoTransform() */
3978 : /************************************************************************/
3979 :
3980 73 : CPLErr HFADataset::SetGeoTransform( double * padfTransform )
3981 :
3982 : {
3983 73 : memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
3984 73 : bGeoDirty = TRUE;
3985 :
3986 73 : return CE_None;
3987 : }
3988 :
3989 : /************************************************************************/
3990 : /* IRasterIO() */
3991 : /* */
3992 : /* Multi-band raster io handler. Here we ensure that the block */
3993 : /* based loading is used for spill file rasters. That is */
3994 : /* because they are effectively pixel interleaved, so */
3995 : /* processing all bands for a given block together avoid extra */
3996 : /* seeks. */
3997 : /************************************************************************/
3998 :
3999 55 : CPLErr HFADataset::IRasterIO( GDALRWFlag eRWFlag,
4000 : int nXOff, int nYOff, int nXSize, int nYSize,
4001 : void *pData, int nBufXSize, int nBufYSize,
4002 : GDALDataType eBufType,
4003 : int nBandCount, int *panBandMap,
4004 : int nPixelSpace, int nLineSpace, int nBandSpace )
4005 :
4006 : {
4007 55 : if( hHFA->papoBand[panBandMap[0]-1]->fpExternal != NULL
4008 : && nBandCount > 1 )
4009 : return GDALDataset::BlockBasedRasterIO(
4010 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
4011 : pData, nBufXSize, nBufYSize, eBufType,
4012 0 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace );
4013 : else
4014 : return
4015 : GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
4016 : pData, nBufXSize, nBufYSize, eBufType,
4017 : nBandCount, panBandMap,
4018 55 : nPixelSpace, nLineSpace, nBandSpace );
4019 : }
4020 :
4021 : /************************************************************************/
4022 : /* UseXFormStack() */
4023 : /************************************************************************/
4024 :
4025 1 : void HFADataset::UseXFormStack( int nStepCount,
4026 : Efga_Polynomial *pasPLForward,
4027 : Efga_Polynomial *pasPLReverse )
4028 :
4029 : {
4030 : /* -------------------------------------------------------------------- */
4031 : /* Generate GCPs using the transform. */
4032 : /* -------------------------------------------------------------------- */
4033 : double dfXRatio, dfYRatio;
4034 :
4035 1 : nGCPCount = 0;
4036 1 : GDALInitGCPs( 36, asGCPList );
4037 :
4038 7 : for( dfYRatio = 0.0; dfYRatio < 1.001; dfYRatio += 0.2 )
4039 : {
4040 42 : for( dfXRatio = 0.0; dfXRatio < 1.001; dfXRatio += 0.2 )
4041 : {
4042 36 : double dfLine = 0.5 + (GetRasterYSize()-1) * dfYRatio;
4043 36 : double dfPixel = 0.5 + (GetRasterXSize()-1) * dfXRatio;
4044 36 : int iGCP = nGCPCount;
4045 :
4046 36 : asGCPList[iGCP].dfGCPPixel = dfPixel;
4047 36 : asGCPList[iGCP].dfGCPLine = dfLine;
4048 :
4049 36 : asGCPList[iGCP].dfGCPX = dfPixel;
4050 36 : asGCPList[iGCP].dfGCPY = dfLine;
4051 36 : asGCPList[iGCP].dfGCPZ = 0.0;
4052 :
4053 36 : if( HFAEvaluateXFormStack( nStepCount, FALSE, pasPLReverse,
4054 : &(asGCPList[iGCP].dfGCPX),
4055 : &(asGCPList[iGCP].dfGCPY) ) )
4056 36 : nGCPCount++;
4057 : }
4058 : }
4059 :
4060 : /* -------------------------------------------------------------------- */
4061 : /* Store the transform as metadata. */
4062 : /* -------------------------------------------------------------------- */
4063 : int iStep, i;
4064 :
4065 : GDALMajorObject::SetMetadataItem(
4066 : "XFORM_STEPS",
4067 : CPLString().Printf("%d",nStepCount),
4068 1 : "XFORMS" );
4069 :
4070 3 : for( iStep = 0; iStep < nStepCount; iStep++ )
4071 : {
4072 : GDALMajorObject::SetMetadataItem(
4073 : CPLString().Printf("XFORM%d_ORDER", iStep),
4074 2 : CPLString().Printf("%d",pasPLForward[iStep].order),
4075 2 : "XFORMS" );
4076 :
4077 2 : if( pasPLForward[iStep].order == 1 )
4078 : {
4079 10 : for( i = 0; i < 4; i++ )
4080 : GDALMajorObject::SetMetadataItem(
4081 : CPLString().Printf("XFORM%d_POLYCOEFMTX[%d]", iStep, i),
4082 : CPLString().Printf("%.15g",
4083 4 : pasPLForward[iStep].polycoefmtx[i]),
4084 4 : "XFORMS" );
4085 :
4086 6 : for( i = 0; i < 2; i++ )
4087 : GDALMajorObject::SetMetadataItem(
4088 : CPLString().Printf("XFORM%d_POLYCOEFVECTOR[%d]", iStep, i),
4089 : CPLString().Printf("%.15g",
4090 2 : pasPLForward[iStep].polycoefvector[i]),
4091 2 : "XFORMS" );
4092 :
4093 1 : continue;
4094 : }
4095 :
4096 : int nCoefCount;
4097 :
4098 1 : if( pasPLForward[iStep].order == 2 )
4099 0 : nCoefCount = 10;
4100 : else
4101 : {
4102 1 : CPLAssert( pasPLForward[iStep].order == 3 );
4103 1 : nCoefCount = 18;
4104 : }
4105 :
4106 38 : for( i = 0; i < nCoefCount; i++ )
4107 : GDALMajorObject::SetMetadataItem(
4108 : CPLString().Printf("XFORM%d_FWD_POLYCOEFMTX[%d]", iStep, i),
4109 : CPLString().Printf("%.15g",
4110 18 : pasPLForward[iStep].polycoefmtx[i]),
4111 18 : "XFORMS" );
4112 :
4113 6 : for( i = 0; i < 2; i++ )
4114 : GDALMajorObject::SetMetadataItem(
4115 : CPLString().Printf("XFORM%d_FWD_POLYCOEFVECTOR[%d]", iStep, i),
4116 : CPLString().Printf("%.15g",
4117 2 : pasPLForward[iStep].polycoefvector[i]),
4118 2 : "XFORMS" );
4119 :
4120 38 : for( i = 0; i < nCoefCount; i++ )
4121 : GDALMajorObject::SetMetadataItem(
4122 : CPLString().Printf("XFORM%d_REV_POLYCOEFMTX[%d]", iStep, i),
4123 : CPLString().Printf("%.15g",
4124 18 : pasPLReverse[iStep].polycoefmtx[i]),
4125 18 : "XFORMS" );
4126 :
4127 6 : for( i = 0; i < 2; i++ )
4128 : GDALMajorObject::SetMetadataItem(
4129 : CPLString().Printf("XFORM%d_REV_POLYCOEFVECTOR[%d]", iStep, i),
4130 : CPLString().Printf("%.15g",
4131 2 : pasPLReverse[iStep].polycoefvector[i]),
4132 2 : "XFORMS" );
4133 : }
4134 1 : }
4135 :
4136 : /************************************************************************/
4137 : /* GetGCPCount() */
4138 : /************************************************************************/
4139 :
4140 10 : int HFADataset::GetGCPCount()
4141 :
4142 : {
4143 10 : return nGCPCount;
4144 : }
4145 :
4146 : /************************************************************************/
4147 : /* GetGCPProjection() */
4148 : /************************************************************************/
4149 :
4150 0 : const char *HFADataset::GetGCPProjection()
4151 :
4152 : {
4153 0 : if( nGCPCount > 0 )
4154 0 : return pszProjection;
4155 : else
4156 0 : return "";
4157 : }
4158 :
4159 : /************************************************************************/
4160 : /* GetGCPs() */
4161 : /************************************************************************/
4162 :
4163 1 : const GDAL_GCP *HFADataset::GetGCPs()
4164 :
4165 : {
4166 1 : return asGCPList;
4167 : }
4168 :
4169 : /************************************************************************/
4170 : /* GetFileList() */
4171 : /************************************************************************/
4172 :
4173 86 : char **HFADataset::GetFileList()
4174 :
4175 : {
4176 86 : char **papszFileList = GDALPamDataset::GetFileList();
4177 :
4178 86 : if( HFAGetIGEFilename( hHFA ) != NULL )
4179 : {
4180 : papszFileList = CSLAddString( papszFileList,
4181 13 : HFAGetIGEFilename( hHFA ) );
4182 : }
4183 :
4184 : // Request an overview to force opening of dependent overview
4185 : // files.
4186 172 : if( nBands > 0
4187 86 : && GetRasterBand(1)->GetOverviewCount() > 0 )
4188 13 : GetRasterBand(1)->GetOverview(0);
4189 :
4190 86 : if( hHFA->psDependent != NULL )
4191 : {
4192 7 : HFAInfo_t *psDep = hHFA->psDependent;
4193 :
4194 : papszFileList =
4195 : CSLAddString( papszFileList,
4196 : CPLFormFilename( psDep->pszPath,
4197 7 : psDep->pszFilename, NULL ));
4198 :
4199 7 : if( HFAGetIGEFilename( psDep ) != NULL )
4200 : papszFileList = CSLAddString( papszFileList,
4201 5 : HFAGetIGEFilename( psDep ) );
4202 : }
4203 :
4204 86 : return papszFileList;
4205 : }
4206 :
4207 : /************************************************************************/
4208 : /* Create() */
4209 : /************************************************************************/
4210 :
4211 136 : GDALDataset *HFADataset::Create( const char * pszFilenameIn,
4212 : int nXSize, int nYSize, int nBands,
4213 : GDALDataType eType,
4214 : char ** papszParmList )
4215 :
4216 : {
4217 : int nHfaDataType;
4218 136 : int nBits = 0;
4219 : const char *pszPixelType;
4220 :
4221 :
4222 136 : if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
4223 2 : nBits = atoi(CSLFetchNameValue(papszParmList,"NBITS"));
4224 :
4225 : pszPixelType =
4226 136 : CSLFetchNameValue( papszParmList, "PIXELTYPE" );
4227 136 : if( pszPixelType == NULL )
4228 136 : pszPixelType = "";
4229 :
4230 : /* -------------------------------------------------------------------- */
4231 : /* Translate the data type. */
4232 : /* -------------------------------------------------------------------- */
4233 136 : switch( eType )
4234 : {
4235 : case GDT_Byte:
4236 66 : if( nBits == 1 )
4237 2 : nHfaDataType = EPT_u1;
4238 64 : else if( nBits == 2 )
4239 0 : nHfaDataType = EPT_u2;
4240 64 : else if( nBits == 4 )
4241 0 : nHfaDataType = EPT_u4;
4242 64 : else if( EQUAL(pszPixelType,"SIGNEDBYTE") )
4243 0 : nHfaDataType = EPT_s8;
4244 : else
4245 64 : nHfaDataType = EPT_u8;
4246 66 : break;
4247 :
4248 : case GDT_UInt16:
4249 11 : nHfaDataType = EPT_u16;
4250 11 : break;
4251 :
4252 : case GDT_Int16:
4253 7 : nHfaDataType = EPT_s16;
4254 7 : break;
4255 :
4256 : case GDT_Int32:
4257 8 : nHfaDataType = EPT_s32;
4258 8 : break;
4259 :
4260 : case GDT_UInt32:
4261 7 : nHfaDataType = EPT_u32;
4262 7 : break;
4263 :
4264 : case GDT_Float32:
4265 7 : nHfaDataType = EPT_f32;
4266 7 : break;
4267 :
4268 : case GDT_Float64:
4269 10 : nHfaDataType = EPT_f64;
4270 10 : break;
4271 :
4272 : case GDT_CFloat32:
4273 7 : nHfaDataType = EPT_c64;
4274 7 : break;
4275 :
4276 : case GDT_CFloat64:
4277 7 : nHfaDataType = EPT_c128;
4278 7 : break;
4279 :
4280 : default:
4281 : CPLError( CE_Failure, CPLE_NotSupported,
4282 : "Data type %s not supported by Erdas Imagine (HFA) format.\n",
4283 6 : GDALGetDataTypeName( eType ) );
4284 6 : return NULL;
4285 :
4286 : }
4287 :
4288 : /* -------------------------------------------------------------------- */
4289 : /* Create the new file. */
4290 : /* -------------------------------------------------------------------- */
4291 : HFAHandle hHFA;
4292 :
4293 : hHFA = HFACreate( pszFilenameIn, nXSize, nYSize, nBands,
4294 130 : nHfaDataType, papszParmList );
4295 130 : if( hHFA == NULL )
4296 2 : return NULL;
4297 :
4298 128 : HFAClose( hHFA );
4299 :
4300 : /* -------------------------------------------------------------------- */
4301 : /* Open the dataset normally. */
4302 : /* -------------------------------------------------------------------- */
4303 128 : HFADataset *poDS = (HFADataset *) GDALOpen( pszFilenameIn, GA_Update );
4304 :
4305 : /* -------------------------------------------------------------------- */
4306 : /* Special creation option to disable checking for UTM */
4307 : /* parameters when writing the projection. This is a special */
4308 : /* hack for sam.gillingham@nrm.qld.gov.au. */
4309 : /* -------------------------------------------------------------------- */
4310 128 : if( poDS != NULL )
4311 : {
4312 : poDS->bIgnoreUTM = CSLFetchBoolean( papszParmList, "IGNOREUTM",
4313 126 : FALSE );
4314 : }
4315 :
4316 : /* -------------------------------------------------------------------- */
4317 : /* Sometimes we can improve ArcGIS compatability by forcing */
4318 : /* generation of a PEString instead of traditional Imagine */
4319 : /* coordinate system descriptions. */
4320 : /* -------------------------------------------------------------------- */
4321 128 : if( poDS != NULL )
4322 : {
4323 : poDS->bForceToPEString =
4324 126 : CSLFetchBoolean( papszParmList, "FORCETOPESTRING", FALSE );
4325 : }
4326 :
4327 128 : return poDS;
4328 :
4329 : }
4330 :
4331 : /************************************************************************/
4332 : /* Rename() */
4333 : /* */
4334 : /* Custom Rename() implementation that knows how to update */
4335 : /* filename references in .img and .aux files. */
4336 : /************************************************************************/
4337 :
4338 1 : CPLErr HFADataset::Rename( const char *pszNewName, const char *pszOldName )
4339 :
4340 : {
4341 : /* -------------------------------------------------------------------- */
4342 : /* Rename all the files at the filesystem level. */
4343 : /* -------------------------------------------------------------------- */
4344 1 : GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
4345 :
4346 1 : CPLErr eErr = poDriver->DefaultRename( pszNewName, pszOldName );
4347 :
4348 1 : if( eErr != CE_None )
4349 0 : return eErr;
4350 :
4351 : /* -------------------------------------------------------------------- */
4352 : /* Now try to go into the .img file and update RRDNames[] */
4353 : /* lists. */
4354 : /* -------------------------------------------------------------------- */
4355 1 : CPLString osOldBasename, osNewBasename;
4356 :
4357 1 : osOldBasename = CPLGetBasename( pszOldName );
4358 1 : osNewBasename = CPLGetBasename( pszNewName );
4359 :
4360 1 : if( osOldBasename != osNewBasename )
4361 : {
4362 1 : HFAHandle hHFA = HFAOpen( pszNewName, "r+" );
4363 :
4364 1 : if( hHFA != NULL )
4365 : {
4366 1 : eErr = HFARenameReferences( hHFA, osNewBasename, osOldBasename );
4367 :
4368 1 : HFAGetOverviewCount( hHFA, 1 );
4369 :
4370 1 : if( hHFA->psDependent != NULL )
4371 : HFARenameReferences( hHFA->psDependent,
4372 1 : osNewBasename, osOldBasename );
4373 :
4374 1 : HFAClose( hHFA );
4375 : }
4376 : }
4377 :
4378 1 : return eErr;
4379 : }
4380 :
4381 : /************************************************************************/
4382 : /* CopyFiles() */
4383 : /* */
4384 : /* Custom CopyFiles() implementation that knows how to update */
4385 : /* filename references in .img and .aux files. */
4386 : /************************************************************************/
4387 :
4388 1 : CPLErr HFADataset::CopyFiles( const char *pszNewName, const char *pszOldName )
4389 :
4390 : {
4391 : /* -------------------------------------------------------------------- */
4392 : /* Rename all the files at the filesystem level. */
4393 : /* -------------------------------------------------------------------- */
4394 1 : GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
4395 :
4396 1 : CPLErr eErr = poDriver->DefaultCopyFiles( pszNewName, pszOldName );
4397 :
4398 1 : if( eErr != CE_None )
4399 0 : return eErr;
4400 :
4401 : /* -------------------------------------------------------------------- */
4402 : /* Now try to go into the .img file and update RRDNames[] */
4403 : /* lists. */
4404 : /* -------------------------------------------------------------------- */
4405 1 : CPLString osOldBasename, osNewBasename;
4406 :
4407 1 : osOldBasename = CPLGetBasename( pszOldName );
4408 1 : osNewBasename = CPLGetBasename( pszNewName );
4409 :
4410 1 : if( osOldBasename != osNewBasename )
4411 : {
4412 1 : HFAHandle hHFA = HFAOpen( pszNewName, "r+" );
4413 :
4414 1 : if( hHFA != NULL )
4415 : {
4416 1 : eErr = HFARenameReferences( hHFA, osNewBasename, osOldBasename );
4417 :
4418 1 : HFAGetOverviewCount( hHFA, 1 );
4419 :
4420 1 : if( hHFA->psDependent != NULL )
4421 : HFARenameReferences( hHFA->psDependent,
4422 1 : osNewBasename, osOldBasename );
4423 :
4424 1 : HFAClose( hHFA );
4425 : }
4426 : }
4427 :
4428 1 : return eErr;
4429 : }
4430 :
4431 : /************************************************************************/
4432 : /* CreateCopy() */
4433 : /************************************************************************/
4434 :
4435 : GDALDataset *
4436 46 : HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
4437 : int bStrict, char ** papszOptions,
4438 : GDALProgressFunc pfnProgress, void * pProgressData )
4439 :
4440 : {
4441 : HFADataset *poDS;
4442 46 : GDALDataType eType = GDT_Byte;
4443 : int iBand;
4444 46 : int nBandCount = poSrcDS->GetRasterCount();
4445 46 : char **papszModOptions = CSLDuplicate( papszOptions );
4446 :
4447 : /* -------------------------------------------------------------------- */
4448 : /* Do we really just want to create an .aux file? */
4449 : /* -------------------------------------------------------------------- */
4450 46 : int bCreateAux = CSLFetchBoolean( papszOptions, "AUX", FALSE );
4451 :
4452 : /* -------------------------------------------------------------------- */
4453 : /* Establish a representative data type to use. */
4454 : /* -------------------------------------------------------------------- */
4455 46 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
4456 0 : return NULL;
4457 :
4458 101 : for( iBand = 0; iBand < nBandCount; iBand++ )
4459 : {
4460 55 : GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
4461 55 : eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
4462 : }
4463 :
4464 : /* -------------------------------------------------------------------- */
4465 : /* If we have PIXELTYPE metadadata in the source, pass it */
4466 : /* through as a creation option. */
4467 : /* -------------------------------------------------------------------- */
4468 70 : if( CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL
4469 : && nBandCount > 0
4470 : && eType == GDT_Byte
4471 : && poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE",
4472 24 : "IMAGE_STRUCTURE" ) )
4473 : {
4474 : papszModOptions =
4475 : CSLSetNameValue( papszModOptions, "PIXELTYPE",
4476 : poSrcDS->GetRasterBand(1)->GetMetadataItem(
4477 0 : "PIXELTYPE", "IMAGE_STRUCTURE" ) );
4478 : }
4479 :
4480 : /* -------------------------------------------------------------------- */
4481 : /* Create the file. */
4482 : /* -------------------------------------------------------------------- */
4483 : poDS = (HFADataset *) Create( pszFilename,
4484 : poSrcDS->GetRasterXSize(),
4485 : poSrcDS->GetRasterYSize(),
4486 : nBandCount,
4487 46 : eType, papszModOptions );
4488 :
4489 46 : CSLDestroy( papszModOptions );
4490 :
4491 46 : if( poDS == NULL )
4492 5 : return NULL;
4493 :
4494 : /* -------------------------------------------------------------------- */
4495 : /* Does the source have a PCT for any of the bands? If so, */
4496 : /* copy it over. */
4497 : /* -------------------------------------------------------------------- */
4498 92 : for( iBand = 0; iBand < nBandCount; iBand++ )
4499 : {
4500 51 : GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
4501 : GDALColorTable *poCT;
4502 :
4503 51 : poCT = poBand->GetColorTable();
4504 51 : if( poCT != NULL )
4505 : {
4506 1 : poDS->GetRasterBand(iBand+1)->SetColorTable(poCT);
4507 : }
4508 : }
4509 :
4510 : /* -------------------------------------------------------------------- */
4511 : /* Do we have metadata for any of the bands or the dataset as a */
4512 : /* whole? */
4513 : /* -------------------------------------------------------------------- */
4514 41 : if( poSrcDS->GetMetadata() != NULL )
4515 28 : poDS->SetMetadata( poSrcDS->GetMetadata() );
4516 :
4517 92 : for( iBand = 0; iBand < nBandCount; iBand++ )
4518 : {
4519 : int bSuccess;
4520 51 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
4521 51 : GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand+1);
4522 :
4523 51 : if( poSrcBand->GetMetadata() != NULL )
4524 4 : poDstBand->SetMetadata( poSrcBand->GetMetadata() );
4525 :
4526 51 : if( strlen(poSrcBand->GetDescription()) > 0 )
4527 4 : poDstBand->SetDescription( poSrcBand->GetDescription() );
4528 :
4529 51 : double dfNoDataValue = poSrcBand->GetNoDataValue( &bSuccess );
4530 51 : if( bSuccess )
4531 2 : poDstBand->SetNoDataValue( dfNoDataValue );
4532 : }
4533 :
4534 : /* -------------------------------------------------------------------- */
4535 : /* Copy projection information. */
4536 : /* -------------------------------------------------------------------- */
4537 : double adfGeoTransform[6];
4538 : const char *pszProj;
4539 :
4540 82 : if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
4541 41 : && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
4542 0 : || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
4543 0 : || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0))
4544 41 : poDS->SetGeoTransform( adfGeoTransform );
4545 :
4546 41 : pszProj = poSrcDS->GetProjectionRef();
4547 41 : if( pszProj != NULL && strlen(pszProj) > 0 )
4548 39 : poDS->SetProjection( pszProj );
4549 :
4550 : /* -------------------------------------------------------------------- */
4551 : /* Copy the imagery. */
4552 : /* -------------------------------------------------------------------- */
4553 41 : if( !bCreateAux )
4554 : {
4555 : CPLErr eErr;
4556 :
4557 : eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
4558 : (GDALDatasetH) poDS,
4559 41 : NULL, pfnProgress, pProgressData );
4560 :
4561 41 : if( eErr != CE_None )
4562 : {
4563 0 : delete poDS;
4564 0 : return NULL;
4565 : }
4566 : }
4567 :
4568 : /* -------------------------------------------------------------------- */
4569 : /* Do we want to generate statistics and a histogram? */
4570 : /* -------------------------------------------------------------------- */
4571 41 : if( CSLFetchBoolean( papszOptions, "STATISTICS", FALSE ) )
4572 : {
4573 2 : for( iBand = 0; iBand < nBandCount; iBand++ )
4574 : {
4575 1 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
4576 : double dfMin, dfMax, dfMean, dfStdDev;
4577 1 : char **papszStatsMD = NULL;
4578 :
4579 : // -----------------------------------------------------------
4580 : // Statistics
4581 : // -----------------------------------------------------------
4582 :
4583 2 : if( poSrcBand->GetStatistics( TRUE, FALSE, &dfMin, &dfMax,
4584 1 : &dfMean, &dfStdDev ) == CE_None
4585 : || poSrcBand->ComputeStatistics( TRUE, &dfMin, &dfMax,
4586 : &dfMean, &dfStdDev,
4587 1 : pfnProgress, pProgressData )
4588 : == CE_None )
4589 : {
4590 1 : CPLString osValue;
4591 :
4592 : papszStatsMD =
4593 : CSLSetNameValue( papszStatsMD, "STATISTICS_MINIMUM",
4594 1 : osValue.Printf( "%.15g", dfMin ) );
4595 : papszStatsMD =
4596 : CSLSetNameValue( papszStatsMD, "STATISTICS_MAXIMUM",
4597 1 : osValue.Printf( "%.15g", dfMax ) );
4598 : papszStatsMD =
4599 : CSLSetNameValue( papszStatsMD, "STATISTICS_MEAN",
4600 1 : osValue.Printf( "%.15g", dfMean ) );
4601 : papszStatsMD =
4602 : CSLSetNameValue( papszStatsMD, "STATISTICS_STDDEV",
4603 1 : osValue.Printf( "%.15g", dfStdDev ) );
4604 : }
4605 :
4606 : // -----------------------------------------------------------
4607 : // Histogram
4608 : // -----------------------------------------------------------
4609 :
4610 1 : int nBuckets, *panHistogram = NULL;
4611 :
4612 1 : if( poSrcBand->GetDefaultHistogram( &dfMin, &dfMax,
4613 : &nBuckets, &panHistogram,
4614 : TRUE,
4615 1 : pfnProgress, pProgressData )
4616 : == CE_None )
4617 : {
4618 1 : CPLString osValue;
4619 1 : char *pszBinValues = (char *) CPLCalloc(12,nBuckets+1);
4620 1 : int iBin, nBinValuesLen = 0;
4621 1 : double dfBinWidth = (dfMax - dfMin) / nBuckets;
4622 :
4623 : papszStatsMD = CSLSetNameValue(
4624 : papszStatsMD, "STATISTICS_HISTOMIN",
4625 1 : osValue.Printf( "%.15g", dfMin+dfBinWidth*0.5 ) );
4626 : papszStatsMD = CSLSetNameValue(
4627 : papszStatsMD, "STATISTICS_HISTOMAX",
4628 1 : osValue.Printf( "%.15g", dfMax-dfBinWidth*0.5 ) );
4629 : papszStatsMD =
4630 : CSLSetNameValue( papszStatsMD, "STATISTICS_HISTONUMBINS",
4631 1 : osValue.Printf( "%d", nBuckets ) );
4632 :
4633 257 : for( iBin = 0; iBin < nBuckets; iBin++ )
4634 : {
4635 :
4636 : strcat( pszBinValues+nBinValuesLen,
4637 256 : osValue.Printf( "%d", panHistogram[iBin]) );
4638 256 : strcat( pszBinValues+nBinValuesLen, "|" );
4639 256 : nBinValuesLen += strlen(pszBinValues+nBinValuesLen);
4640 : }
4641 : papszStatsMD =
4642 : CSLSetNameValue( papszStatsMD, "STATISTICS_HISTOBINVALUES",
4643 1 : pszBinValues );
4644 1 : CPLFree( pszBinValues );
4645 : }
4646 :
4647 1 : CPLFree(panHistogram);
4648 :
4649 1 : if( CSLCount(papszStatsMD) > 0 )
4650 1 : HFASetMetadata( poDS->hHFA, iBand+1, papszStatsMD );
4651 :
4652 1 : CSLDestroy( papszStatsMD );
4653 : }
4654 : }
4655 :
4656 : /* -------------------------------------------------------------------- */
4657 : /* All report completion. */
4658 : /* -------------------------------------------------------------------- */
4659 41 : if( !pfnProgress( 1.0, NULL, pProgressData ) )
4660 : {
4661 : CPLError( CE_Failure, CPLE_UserInterrupt,
4662 0 : "User terminated" );
4663 0 : delete poDS;
4664 :
4665 : GDALDriver *poHFADriver =
4666 0 : (GDALDriver *) GDALGetDriverByName( "HFA" );
4667 0 : poHFADriver->Delete( pszFilename );
4668 0 : return NULL;
4669 : }
4670 :
4671 41 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
4672 :
4673 41 : return poDS;
4674 : }
4675 :
4676 : /************************************************************************/
4677 : /* GDALRegister_HFA() */
4678 : /************************************************************************/
4679 :
4680 558 : void GDALRegister_HFA()
4681 :
4682 : {
4683 : GDALDriver *poDriver;
4684 :
4685 558 : if( GDALGetDriverByName( "HFA" ) == NULL )
4686 : {
4687 537 : poDriver = new GDALDriver();
4688 :
4689 537 : poDriver->SetDescription( "HFA" );
4690 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
4691 537 : "Erdas Imagine Images (.img)" );
4692 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
4693 537 : "frmt_hfa.html" );
4694 537 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
4695 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
4696 537 : "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CFloat32 CFloat64" );
4697 :
4698 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
4699 : "<CreationOptionList>"
4700 : " <Option name='BLOCKSIZE' type='integer' description='tile width/height (32-2048)' default='64'/>"
4701 : " <Option name='USE_SPILL' type='boolean' description='Force use of spill file'/>"
4702 : " <Option name='COMPRESSED' alias='COMPRESS' type='boolean' description='compress blocks'/>"
4703 : " <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
4704 : " <Option name='AUX' type='boolean' description='Create an .aux file'/>"
4705 : " <Option name='IGNOREUTM' type='boolean' description='Ignore UTM when selecting coordinate system - will use Transverse Mercator. Only used for Create() method'/>"
4706 : " <Option name='NBITS' type='integer' description='Create file with special sub-byte data type (1/2/4)'/>"
4707 : " <Option name='STATISTICS' type='boolean' description='Generate statistics and a histogram'/>"
4708 : " <Option name='DEPENDENT_FILE' type='string' description='Name of dependent file (must not have absolute path)'/>"
4709 : " <Option name='FORCETOPESTRING' type='boolean' description='Force use of ArcGIS PE String in file instead of Imagine coordinate system format'/>"
4710 537 : "</CreationOptionList>" );
4711 :
4712 537 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
4713 :
4714 537 : poDriver->pfnOpen = HFADataset::Open;
4715 537 : poDriver->pfnCreate = HFADataset::Create;
4716 537 : poDriver->pfnCreateCopy = HFADataset::CreateCopy;
4717 537 : poDriver->pfnIdentify = HFADataset::Identify;
4718 537 : poDriver->pfnRename = HFADataset::Rename;
4719 537 : poDriver->pfnCopyFiles = HFADataset::CopyFiles;
4720 :
4721 :
4722 537 : GetGDALDriverManager()->RegisterDriver( poDriver );
4723 : }
4724 558 : }
4725 :
|