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