1 : /******************************************************************************
2 : * $Id: hfaopen.cpp 21870 2011-02-26 21:34:38Z warmerdam $
3 : *
4 : * Project: Erdas Imagine (.img) Translator
5 : * Purpose: Supporting functions for HFA (.img) ... main (C callable) API
6 : * that is not dependent on GDAL (just CPL).
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Intergraph Corporation
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 : * hfaopen.cpp
32 : *
33 : * Supporting routines for reading Erdas Imagine (.imf) Heirarchical
34 : * File Architecture files. This is intended to be a library independent
35 : * of the GDAL core, but dependent on the Common Portability Library.
36 : *
37 : */
38 :
39 : #include "hfa_p.h"
40 : #include "cpl_conv.h"
41 : #include <limits.h>
42 : #include <vector>
43 :
44 : CPL_CVSID("$Id: hfaopen.cpp 21870 2011-02-26 21:34:38Z warmerdam $");
45 :
46 :
47 : static const char *apszAuxMetadataItems[] = {
48 :
49 : // node/entry field_name metadata_key type
50 :
51 : "Statistics", "dminimum", "STATISTICS_MINIMUM", "Esta_Statistics",
52 : "Statistics", "dmaximum", "STATISTICS_MAXIMUM", "Esta_Statistics",
53 : "Statistics", "dmean", "STATISTICS_MEAN", "Esta_Statistics",
54 : "Statistics", "dmedian", "STATISTICS_MEDIAN", "Esta_Statistics",
55 : "Statistics", "dmode", "STATISTICS_MODE", "Esta_Statistics",
56 : "Statistics", "dstddev", "STATISTICS_STDDEV", "Esta_Statistics",
57 : "HistogramParameters", "lBinFunction.numBins", "STATISTICS_HISTONUMBINS","Eimg_StatisticsParameters830",
58 : "HistogramParameters", "dBinFunction.minLimit", "STATISTICS_HISTOMIN", "Eimg_StatisticsParameters830",
59 : "HistogramParameters", "dBinFunction.maxLimit", "STATISTICS_HISTOMAX", "Eimg_StatisticsParameters830",
60 : "StatisticsParameters", "lSkipFactorX", "STATISTICS_SKIPFACTORX", "",
61 : "StatisticsParameters", "lSkipFactorY", "STATISTICS_SKIPFACTORY", "",
62 : "StatisticsParameters", "dExcludedValues", "STATISTICS_EXCLUDEDVALUES","",
63 : "", "elayerType", "LAYER_TYPE", "",
64 : NULL
65 : };
66 :
67 :
68 501 : const char ** GetHFAAuxMetaDataList()
69 : {
70 501 : return apszAuxMetadataItems;
71 : }
72 :
73 :
74 : /************************************************************************/
75 : /* HFAGetDictionary() */
76 : /************************************************************************/
77 :
78 395 : static char * HFAGetDictionary( HFAHandle hHFA )
79 :
80 : {
81 395 : int nDictMax = 100;
82 395 : char *pszDictionary = (char *) CPLMalloc(nDictMax);
83 395 : int nDictSize = 0;
84 :
85 395 : VSIFSeekL( hHFA->fp, hHFA->nDictionaryPos, SEEK_SET );
86 :
87 1461163 : while( TRUE )
88 : {
89 1461558 : if( nDictSize >= nDictMax-1 )
90 : {
91 1964 : nDictMax = nDictSize * 2 + 100;
92 1964 : pszDictionary = (char *) CPLRealloc(pszDictionary, nDictMax );
93 : }
94 :
95 4497103 : if( VSIFReadL( pszDictionary + nDictSize, 1, 1, hHFA->fp ) < 1
96 1461534 : || pszDictionary[nDictSize] == '\0'
97 1459979 : || (nDictSize > 2 && pszDictionary[nDictSize-2] == ','
98 114032 : && pszDictionary[nDictSize-1] == '.') )
99 : break;
100 :
101 1461163 : nDictSize++;
102 : }
103 :
104 395 : pszDictionary[nDictSize] = '\0';
105 :
106 :
107 395 : return( pszDictionary );
108 : }
109 :
110 : /************************************************************************/
111 : /* HFAOpen() */
112 : /************************************************************************/
113 :
114 395 : HFAHandle HFAOpen( const char * pszFilename, const char * pszAccess )
115 :
116 : {
117 : VSILFILE *fp;
118 : char szHeader[16];
119 : HFAInfo_t *psInfo;
120 : GUInt32 nHeaderPos;
121 :
122 : /* -------------------------------------------------------------------- */
123 : /* Open the file. */
124 : /* -------------------------------------------------------------------- */
125 647 : if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb" ) )
126 252 : fp = VSIFOpenL( pszFilename, "rb" );
127 : else
128 143 : fp = VSIFOpenL( pszFilename, "r+b" );
129 :
130 : /* should this be changed to use some sort of CPLFOpen() which will
131 : set the error? */
132 395 : if( fp == NULL )
133 : {
134 : CPLError( CE_Failure, CPLE_OpenFailed,
135 : "File open of %s failed.",
136 0 : pszFilename );
137 :
138 0 : return NULL;
139 : }
140 :
141 : /* -------------------------------------------------------------------- */
142 : /* Read and verify the header. */
143 : /* -------------------------------------------------------------------- */
144 395 : if( VSIFReadL( szHeader, 16, 1, fp ) < 1 )
145 : {
146 : CPLError( CE_Failure, CPLE_AppDefined,
147 : "Attempt to read 16 byte header failed for\n%s.",
148 0 : pszFilename );
149 :
150 0 : return NULL;
151 : }
152 :
153 395 : if( !EQUALN(szHeader,"EHFA_HEADER_TAG",15) )
154 : {
155 : CPLError( CE_Failure, CPLE_AppDefined,
156 : "File %s is not an Imagine HFA file ... header wrong.",
157 0 : pszFilename );
158 :
159 0 : return NULL;
160 : }
161 :
162 : /* -------------------------------------------------------------------- */
163 : /* Create the HFAInfo_t */
164 : /* -------------------------------------------------------------------- */
165 395 : psInfo = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
166 :
167 395 : psInfo->pszFilename = CPLStrdup(CPLGetFilename(pszFilename));
168 395 : psInfo->pszPath = CPLStrdup(CPLGetPath(pszFilename));
169 395 : psInfo->fp = fp;
170 647 : if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb" ) )
171 252 : psInfo->eAccess = HFA_ReadOnly;
172 : else
173 143 : psInfo->eAccess = HFA_Update;
174 395 : psInfo->bTreeDirty = FALSE;
175 :
176 : /* -------------------------------------------------------------------- */
177 : /* Where is the header? */
178 : /* -------------------------------------------------------------------- */
179 395 : VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, fp );
180 : HFAStandard( 4, &nHeaderPos );
181 :
182 : /* -------------------------------------------------------------------- */
183 : /* Read the header. */
184 : /* -------------------------------------------------------------------- */
185 395 : VSIFSeekL( fp, nHeaderPos, SEEK_SET );
186 :
187 395 : VSIFReadL( &(psInfo->nVersion), sizeof(GInt32), 1, fp );
188 : HFAStandard( 4, &(psInfo->nVersion) );
189 :
190 395 : VSIFReadL( szHeader, 4, 1, fp ); /* skip freeList */
191 :
192 395 : VSIFReadL( &(psInfo->nRootPos), sizeof(GInt32), 1, fp );
193 : HFAStandard( 4, &(psInfo->nRootPos) );
194 :
195 395 : VSIFReadL( &(psInfo->nEntryHeaderLength), sizeof(GInt16), 1, fp );
196 : HFAStandard( 2, &(psInfo->nEntryHeaderLength) );
197 :
198 395 : VSIFReadL( &(psInfo->nDictionaryPos), sizeof(GInt32), 1, fp );
199 : HFAStandard( 4, &(psInfo->nDictionaryPos) );
200 :
201 : /* -------------------------------------------------------------------- */
202 : /* Collect file size. */
203 : /* -------------------------------------------------------------------- */
204 395 : VSIFSeekL( fp, 0, SEEK_END );
205 395 : psInfo->nEndOfFile = (GUInt32) VSIFTellL( fp );
206 :
207 : /* -------------------------------------------------------------------- */
208 : /* Instantiate the root entry. */
209 : /* -------------------------------------------------------------------- */
210 395 : psInfo->poRoot = new HFAEntry( psInfo, psInfo->nRootPos, NULL, NULL );
211 :
212 : /* -------------------------------------------------------------------- */
213 : /* Read the dictionary */
214 : /* -------------------------------------------------------------------- */
215 395 : psInfo->pszDictionary = HFAGetDictionary( psInfo );
216 790 : psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary );
217 :
218 : /* -------------------------------------------------------------------- */
219 : /* Collect band definitions. */
220 : /* -------------------------------------------------------------------- */
221 395 : HFAParseBandInfo( psInfo );
222 :
223 395 : return psInfo;
224 : }
225 :
226 : /************************************************************************/
227 : /* HFACreateDependent() */
228 : /* */
229 : /* Create a .rrd file for the named file if it does not exist, */
230 : /* or return the existing dependent if it already exists. */
231 : /************************************************************************/
232 :
233 2 : HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
234 :
235 : {
236 2 : if( psBase->psDependent != NULL )
237 1 : return psBase->psDependent;
238 :
239 : /* -------------------------------------------------------------------- */
240 : /* Create desired RRD filename. */
241 : /* -------------------------------------------------------------------- */
242 1 : CPLString oBasename = CPLGetBasename( psBase->pszFilename );
243 : CPLString oRRDFilename =
244 1 : CPLFormFilename( psBase->pszPath, oBasename, "rrd" );
245 :
246 : /* -------------------------------------------------------------------- */
247 : /* Does this file already exist? If so, re-use it. */
248 : /* -------------------------------------------------------------------- */
249 1 : VSILFILE *fp = VSIFOpenL( oRRDFilename, "rb" );
250 1 : if( fp != NULL )
251 : {
252 0 : VSIFCloseL( fp );
253 0 : psBase->psDependent = HFAOpen( oRRDFilename, "rb" );
254 : }
255 :
256 : /* -------------------------------------------------------------------- */
257 : /* Otherwise create it now. */
258 : /* -------------------------------------------------------------------- */
259 : HFAInfo_t *psDep;
260 1 : psDep = psBase->psDependent = HFACreateLL( oRRDFilename );
261 :
262 : /* -------------------------------------------------------------------- */
263 : /* Add the DependentFile node with the pointer back to the */
264 : /* parent. When working from an .aux file we really want the */
265 : /* .rrd to point back to the original file, not the .aux file. */
266 : /* -------------------------------------------------------------------- */
267 1 : HFAEntry *poEntry = psBase->poRoot->GetNamedChild("DependentFile");
268 1 : const char *pszDependentFile = NULL;
269 1 : if( poEntry != NULL )
270 0 : pszDependentFile = poEntry->GetStringField( "dependent.string" );
271 1 : if( pszDependentFile == NULL )
272 1 : pszDependentFile = psBase->pszFilename;
273 :
274 : HFAEntry *poDF = new HFAEntry( psDep, "DependentFile",
275 1 : "Eimg_DependentFile", psDep->poRoot );
276 :
277 1 : poDF->MakeData( strlen(pszDependentFile) + 50 );
278 1 : poDF->SetPosition();
279 1 : poDF->SetStringField( "dependent.string", pszDependentFile );
280 :
281 1 : return psDep;
282 : }
283 :
284 : /************************************************************************/
285 : /* HFAGetDependent() */
286 : /************************************************************************/
287 :
288 34 : HFAInfo_t *HFAGetDependent( HFAInfo_t *psBase, const char *pszFilename )
289 :
290 : {
291 34 : if( EQUAL(pszFilename,psBase->pszFilename) )
292 13 : return psBase;
293 :
294 21 : if( psBase->psDependent != NULL )
295 : {
296 3 : if( EQUAL(pszFilename,psBase->psDependent->pszFilename) )
297 3 : return psBase->psDependent;
298 : else
299 0 : return NULL;
300 : }
301 :
302 : /* -------------------------------------------------------------------- */
303 : /* Try to open the dependent file. */
304 : /* -------------------------------------------------------------------- */
305 : char *pszDependent;
306 : VSILFILE *fp;
307 18 : const char* pszMode = psBase->eAccess == HFA_Update ? "r+b" : "rb";
308 :
309 : pszDependent = CPLStrdup(
310 18 : CPLFormFilename( psBase->pszPath, pszFilename, NULL ) );
311 :
312 18 : fp = VSIFOpenL( pszDependent, pszMode );
313 18 : if( fp != NULL )
314 : {
315 14 : VSIFCloseL( fp );
316 14 : psBase->psDependent = HFAOpen( pszDependent, pszMode );
317 : }
318 :
319 18 : CPLFree( pszDependent );
320 :
321 18 : return psBase->psDependent;
322 : }
323 :
324 :
325 : /************************************************************************/
326 : /* HFAParseBandInfo() */
327 : /* */
328 : /* This is used by HFAOpen() and HFACreate() to initialize the */
329 : /* band structures. */
330 : /************************************************************************/
331 :
332 523 : CPLErr HFAParseBandInfo( HFAInfo_t *psInfo )
333 :
334 : {
335 : HFAEntry *poNode;
336 :
337 : /* -------------------------------------------------------------------- */
338 : /* Find the first band node. */
339 : /* -------------------------------------------------------------------- */
340 523 : psInfo->nBands = 0;
341 523 : poNode = psInfo->poRoot->GetChild();
342 2282 : while( poNode != NULL )
343 : {
344 1236 : if( EQUAL(poNode->GetType(),"Eimg_Layer")
345 : && poNode->GetIntField("width") > 0
346 : && poNode->GetIntField("height") > 0 )
347 : {
348 614 : if( psInfo->nBands == 0 )
349 : {
350 504 : psInfo->nXSize = poNode->GetIntField("width");
351 504 : psInfo->nYSize = poNode->GetIntField("height");
352 : }
353 110 : else if( poNode->GetIntField("width") != psInfo->nXSize
354 : || poNode->GetIntField("height") != psInfo->nYSize )
355 : {
356 0 : return CE_Failure;
357 : }
358 :
359 : psInfo->papoBand = (HFABand **)
360 : CPLRealloc(psInfo->papoBand,
361 614 : sizeof(HFABand *) * (psInfo->nBands+1));
362 614 : psInfo->papoBand[psInfo->nBands] = new HFABand( psInfo, poNode );
363 614 : if (psInfo->papoBand[psInfo->nBands]->nWidth == 0)
364 : {
365 0 : delete psInfo->papoBand[psInfo->nBands];
366 0 : return CE_Failure;
367 : }
368 614 : psInfo->nBands++;
369 : }
370 :
371 1236 : poNode = poNode->GetNext();
372 : }
373 :
374 523 : return CE_None;
375 : }
376 :
377 : /************************************************************************/
378 : /* HFAClose() */
379 : /************************************************************************/
380 :
381 524 : void HFAClose( HFAHandle hHFA )
382 :
383 : {
384 : int i;
385 :
386 524 : if( hHFA->eAccess == HFA_Update && (hHFA->bTreeDirty || hHFA->poDictionary->bDictionaryTextDirty) )
387 263 : HFAFlush( hHFA );
388 :
389 524 : if( hHFA->psDependent != NULL )
390 14 : HFAClose( hHFA->psDependent );
391 :
392 524 : delete hHFA->poRoot;
393 :
394 524 : VSIFCloseL( hHFA->fp );
395 :
396 524 : if( hHFA->poDictionary != NULL )
397 524 : delete hHFA->poDictionary;
398 :
399 524 : CPLFree( hHFA->pszDictionary );
400 524 : CPLFree( hHFA->pszFilename );
401 524 : CPLFree( hHFA->pszIGEFilename );
402 524 : CPLFree( hHFA->pszPath );
403 :
404 1138 : for( i = 0; i < hHFA->nBands; i++ )
405 : {
406 614 : delete hHFA->papoBand[i];
407 : }
408 :
409 524 : CPLFree( hHFA->papoBand );
410 :
411 524 : if( hHFA->pProParameters != NULL )
412 : {
413 : Eprj_ProParameters *psProParms = (Eprj_ProParameters *)
414 38 : hHFA->pProParameters;
415 :
416 38 : CPLFree( psProParms->proExeName );
417 38 : CPLFree( psProParms->proName );
418 38 : CPLFree( psProParms->proSpheroid.sphereName );
419 :
420 38 : CPLFree( psProParms );
421 : }
422 :
423 524 : if( hHFA->pDatum != NULL )
424 : {
425 38 : CPLFree( ((Eprj_Datum *) hHFA->pDatum)->datumname );
426 38 : CPLFree( ((Eprj_Datum *) hHFA->pDatum)->gridname );
427 38 : CPLFree( hHFA->pDatum );
428 : }
429 :
430 524 : if( hHFA->pMapInfo != NULL )
431 : {
432 160 : CPLFree( ((Eprj_MapInfo *) hHFA->pMapInfo)->proName );
433 160 : CPLFree( ((Eprj_MapInfo *) hHFA->pMapInfo)->units );
434 160 : CPLFree( hHFA->pMapInfo );
435 : }
436 :
437 524 : CPLFree( hHFA );
438 524 : }
439 :
440 : /************************************************************************/
441 : /* HFARemove() */
442 : /* Used from HFADelete() function. */
443 : /************************************************************************/
444 :
445 0 : CPLErr HFARemove( const char *pszFilename )
446 :
447 : {
448 : VSIStatBufL sStat;
449 :
450 0 : if( VSIStatL( pszFilename, &sStat ) == 0 && VSI_ISREG( sStat.st_mode ) )
451 : {
452 0 : if( VSIUnlink( pszFilename ) == 0 )
453 0 : return CE_None;
454 : else
455 : {
456 : CPLError( CE_Failure, CPLE_AppDefined,
457 0 : "Attempt to unlink %s failed.\n", pszFilename );
458 0 : return CE_Failure;
459 : }
460 : }
461 : else
462 : {
463 : CPLError( CE_Failure, CPLE_AppDefined,
464 0 : "Unable to delete %s, not a file.\n", pszFilename );
465 0 : return CE_Failure;
466 : }
467 : }
468 :
469 : /************************************************************************/
470 : /* HFADelete() */
471 : /************************************************************************/
472 :
473 0 : CPLErr HFADelete( const char *pszFilename )
474 :
475 : {
476 0 : HFAInfo_t *psInfo = HFAOpen( pszFilename, "rb" );
477 0 : HFAEntry *poDMS = NULL;
478 0 : HFAEntry *poLayer = NULL;
479 0 : HFAEntry *poNode = NULL;
480 :
481 0 : if( psInfo != NULL )
482 : {
483 0 : poNode = psInfo->poRoot->GetChild();
484 0 : while( ( poNode != NULL ) && ( poLayer == NULL ) )
485 : {
486 0 : if( EQUAL(poNode->GetType(),"Eimg_Layer") )
487 : {
488 0 : poLayer = poNode;
489 : }
490 0 : poNode = poNode->GetNext();
491 : }
492 :
493 0 : if( poLayer != NULL )
494 0 : poDMS = poLayer->GetNamedChild( "ExternalRasterDMS" );
495 :
496 0 : if ( poDMS )
497 : {
498 : const char *pszRawFilename =
499 0 : poDMS->GetStringField( "fileName.string" );
500 :
501 0 : if( pszRawFilename != NULL )
502 : HFARemove( CPLFormFilename( psInfo->pszPath,
503 0 : pszRawFilename, NULL ) );
504 : }
505 :
506 0 : HFAClose( psInfo );
507 : }
508 0 : return HFARemove( pszFilename );
509 : }
510 :
511 : /************************************************************************/
512 : /* HFAGetRasterInfo() */
513 : /************************************************************************/
514 :
515 379 : CPLErr HFAGetRasterInfo( HFAHandle hHFA, int * pnXSize, int * pnYSize,
516 : int * pnBands )
517 :
518 : {
519 379 : if( pnXSize != NULL )
520 379 : *pnXSize = hHFA->nXSize;
521 379 : if( pnYSize != NULL )
522 379 : *pnYSize = hHFA->nYSize;
523 379 : if( pnBands != NULL )
524 379 : *pnBands = hHFA->nBands;
525 379 : return CE_None;
526 : }
527 :
528 : /************************************************************************/
529 : /* HFAGetBandInfo() */
530 : /************************************************************************/
531 :
532 485 : CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, int * pnDataType,
533 : int * pnBlockXSize, int * pnBlockYSize,
534 : int *pnCompressionType )
535 :
536 : {
537 485 : if( nBand < 0 || nBand > hHFA->nBands )
538 : {
539 0 : CPLAssert( FALSE );
540 0 : return CE_Failure;
541 : }
542 :
543 485 : HFABand *poBand = hHFA->papoBand[nBand-1];
544 :
545 485 : if( pnDataType != NULL )
546 485 : *pnDataType = poBand->nDataType;
547 :
548 485 : if( pnBlockXSize != NULL )
549 485 : *pnBlockXSize = poBand->nBlockXSize;
550 :
551 485 : if( pnBlockYSize != NULL )
552 485 : *pnBlockYSize = poBand->nBlockYSize;
553 :
554 : /* -------------------------------------------------------------------- */
555 : /* Get compression code from RasterDMS. */
556 : /* -------------------------------------------------------------------- */
557 485 : if( pnCompressionType != NULL )
558 : {
559 : HFAEntry *poDMS;
560 :
561 485 : *pnCompressionType = 0;
562 :
563 485 : poDMS = poBand->poNode->GetNamedChild( "RasterDMS" );
564 :
565 485 : if( poDMS != NULL )
566 437 : *pnCompressionType = poDMS->GetIntField( "compressionType" );
567 : }
568 :
569 485 : return( CE_None );
570 : }
571 :
572 : /************************************************************************/
573 : /* HFAGetBandNoData() */
574 : /* */
575 : /* returns TRUE if value is set, otherwise FALSE. */
576 : /************************************************************************/
577 :
578 99 : int HFAGetBandNoData( HFAHandle hHFA, int nBand, double *pdfNoData )
579 :
580 : {
581 99 : if( nBand < 0 || nBand > hHFA->nBands )
582 : {
583 0 : CPLAssert( FALSE );
584 0 : return CE_Failure;
585 : }
586 :
587 99 : HFABand *poBand = hHFA->papoBand[nBand-1];
588 :
589 99 : if( !poBand->bNoDataSet && poBand->nOverviews > 0 )
590 9 : poBand = poBand->papoOverviews[0];
591 :
592 99 : *pdfNoData = poBand->dfNoData;
593 99 : return poBand->bNoDataSet;
594 : }
595 :
596 : /************************************************************************/
597 : /* HFASetBandNoData() */
598 : /* */
599 : /* attempts to set a no-data value on the given band */
600 : /************************************************************************/
601 :
602 6 : CPLErr HFASetBandNoData( HFAHandle hHFA, int nBand, double dfValue )
603 :
604 : {
605 6 : if ( nBand < 0 || nBand > hHFA->nBands )
606 : {
607 0 : CPLAssert( FALSE );
608 0 : return CE_Failure;
609 : }
610 :
611 6 : HFABand *poBand = hHFA->papoBand[nBand - 1];
612 :
613 6 : return poBand->SetNoDataValue( dfValue );
614 : }
615 :
616 : /************************************************************************/
617 : /* HFAGetOverviewCount() */
618 : /************************************************************************/
619 :
620 102 : int HFAGetOverviewCount( HFAHandle hHFA, int nBand )
621 :
622 : {
623 : HFABand *poBand;
624 :
625 102 : if( nBand < 0 || nBand > hHFA->nBands )
626 : {
627 0 : CPLAssert( FALSE );
628 0 : return CE_Failure;
629 : }
630 :
631 102 : poBand = hHFA->papoBand[nBand-1];
632 102 : poBand->LoadOverviews();
633 :
634 102 : return poBand->nOverviews;
635 : }
636 :
637 : /************************************************************************/
638 : /* HFAGetOverviewInfo() */
639 : /************************************************************************/
640 :
641 35 : CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
642 : int * pnXSize, int * pnYSize,
643 : int * pnBlockXSize, int * pnBlockYSize,
644 : int * pnHFADataType )
645 :
646 : {
647 : HFABand *poBand;
648 :
649 35 : if( nBand < 0 || nBand > hHFA->nBands )
650 : {
651 0 : CPLAssert( FALSE );
652 0 : return CE_Failure;
653 : }
654 :
655 35 : poBand = hHFA->papoBand[nBand-1];
656 35 : poBand->LoadOverviews();
657 :
658 35 : if( iOverview < 0 || iOverview >= poBand->nOverviews )
659 : {
660 0 : CPLAssert( FALSE );
661 0 : return CE_Failure;
662 : }
663 35 : poBand = poBand->papoOverviews[iOverview];
664 :
665 35 : if( pnXSize != NULL )
666 35 : *pnXSize = poBand->nWidth;
667 :
668 35 : if( pnYSize != NULL )
669 35 : *pnYSize = poBand->nHeight;
670 :
671 35 : if( pnBlockXSize != NULL )
672 35 : *pnBlockXSize = poBand->nBlockXSize;
673 :
674 35 : if( pnBlockYSize != NULL )
675 35 : *pnBlockYSize = poBand->nBlockYSize;
676 :
677 35 : if( pnHFADataType != NULL )
678 35 : *pnHFADataType = poBand->nDataType;
679 :
680 35 : return( CE_None );
681 : }
682 :
683 : /************************************************************************/
684 : /* HFAGetRasterBlock() */
685 : /************************************************************************/
686 :
687 0 : CPLErr HFAGetRasterBlock( HFAHandle hHFA, int nBand,
688 : int nXBlock, int nYBlock, void * pData )
689 :
690 : {
691 0 : return HFAGetRasterBlockEx(hHFA, nBand, nXBlock, nYBlock, pData, -1);
692 : }
693 :
694 : /************************************************************************/
695 : /* HFAGetRasterBlockEx() */
696 : /************************************************************************/
697 :
698 336 : CPLErr HFAGetRasterBlockEx( HFAHandle hHFA, int nBand,
699 : int nXBlock, int nYBlock, void * pData, int nDataSize )
700 :
701 : {
702 336 : if( nBand < 1 || nBand > hHFA->nBands )
703 0 : return CE_Failure;
704 :
705 336 : return( hHFA->papoBand[nBand-1]->GetRasterBlock(nXBlock,nYBlock,pData,nDataSize) );
706 : }
707 :
708 : /************************************************************************/
709 : /* HFAGetOverviewRasterBlock() */
710 : /************************************************************************/
711 :
712 0 : CPLErr HFAGetOverviewRasterBlock( HFAHandle hHFA, int nBand, int iOverview,
713 : int nXBlock, int nYBlock, void * pData )
714 :
715 : {
716 0 : return HFAGetOverviewRasterBlockEx(hHFA, nBand, iOverview, nXBlock, nYBlock, pData, -1);
717 : }
718 :
719 : /************************************************************************/
720 : /* HFAGetOverviewRasterBlockEx() */
721 : /************************************************************************/
722 :
723 34 : CPLErr HFAGetOverviewRasterBlockEx( HFAHandle hHFA, int nBand, int iOverview,
724 : int nXBlock, int nYBlock, void * pData, int nDataSize )
725 :
726 : {
727 34 : if( nBand < 1 || nBand > hHFA->nBands )
728 0 : return CE_Failure;
729 :
730 34 : if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand-1]->nOverviews )
731 0 : return CE_Failure;
732 :
733 68 : return( hHFA->papoBand[nBand-1]->papoOverviews[iOverview]->
734 68 : GetRasterBlock(nXBlock,nYBlock,pData, nDataSize) );
735 : }
736 :
737 : /************************************************************************/
738 : /* HFASetRasterBlock() */
739 : /************************************************************************/
740 :
741 89 : CPLErr HFASetRasterBlock( HFAHandle hHFA, int nBand,
742 : int nXBlock, int nYBlock, void * pData )
743 :
744 : {
745 89 : if( nBand < 1 || nBand > hHFA->nBands )
746 0 : return CE_Failure;
747 :
748 89 : return( hHFA->papoBand[nBand-1]->SetRasterBlock(nXBlock,nYBlock,pData) );
749 : }
750 :
751 : /************************************************************************/
752 : /* HFASetRasterBlock() */
753 : /************************************************************************/
754 :
755 18 : CPLErr HFASetOverviewRasterBlock( HFAHandle hHFA, int nBand, int iOverview,
756 : int nXBlock, int nYBlock, void * pData )
757 :
758 : {
759 18 : if( nBand < 1 || nBand > hHFA->nBands )
760 0 : return CE_Failure;
761 :
762 18 : if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand-1]->nOverviews )
763 0 : return CE_Failure;
764 :
765 36 : return( hHFA->papoBand[nBand-1]->papoOverviews[iOverview]->
766 36 : SetRasterBlock(nXBlock,nYBlock,pData) );
767 : }
768 :
769 : /************************************************************************/
770 : /* HFAGetBandName() */
771 : /************************************************************************/
772 :
773 154 : const char * HFAGetBandName( HFAHandle hHFA, int nBand )
774 : {
775 154 : if( nBand < 1 || nBand > hHFA->nBands )
776 0 : return "";
777 :
778 154 : return( hHFA->papoBand[nBand-1]->GetBandName() );
779 : }
780 :
781 : /************************************************************************/
782 : /* HFASetBandName() */
783 : /************************************************************************/
784 :
785 5 : void HFASetBandName( HFAHandle hHFA, int nBand, const char *pszName )
786 : {
787 5 : if( nBand < 1 || nBand > hHFA->nBands )
788 0 : return;
789 :
790 5 : hHFA->papoBand[nBand-1]->SetBandName( pszName );
791 : }
792 :
793 : /************************************************************************/
794 : /* HFAGetDataTypeBits() */
795 : /************************************************************************/
796 :
797 2820 : int HFAGetDataTypeBits( int nDataType )
798 :
799 : {
800 2820 : switch( nDataType )
801 : {
802 : case EPT_u1:
803 38 : return 1;
804 :
805 : case EPT_u2:
806 3 : return 2;
807 :
808 : case EPT_u4:
809 0 : return 4;
810 :
811 : case EPT_u8:
812 : case EPT_s8:
813 1114 : return 8;
814 :
815 : case EPT_u16:
816 : case EPT_s16:
817 200 : return 16;
818 :
819 : case EPT_u32:
820 : case EPT_s32:
821 : case EPT_f32:
822 272 : return 32;
823 :
824 : case EPT_f64:
825 : case EPT_c64:
826 1120 : return 64;
827 :
828 : case EPT_c128:
829 73 : return 128;
830 : }
831 :
832 0 : return 0;
833 : }
834 :
835 : /************************************************************************/
836 : /* HFAGetDataTypeName() */
837 : /************************************************************************/
838 :
839 0 : const char *HFAGetDataTypeName( int nDataType )
840 :
841 : {
842 0 : switch( nDataType )
843 : {
844 : case EPT_u1:
845 0 : return "u1";
846 :
847 : case EPT_u2:
848 0 : return "u2";
849 :
850 : case EPT_u4:
851 0 : return "u4";
852 :
853 : case EPT_u8:
854 0 : return "u8";
855 :
856 : case EPT_s8:
857 0 : return "s8";
858 :
859 : case EPT_u16:
860 0 : return "u16";
861 :
862 : case EPT_s16:
863 0 : return "s16";
864 :
865 : case EPT_u32:
866 0 : return "u32";
867 :
868 : case EPT_s32:
869 0 : return "s32";
870 :
871 : case EPT_f32:
872 0 : return "f32";
873 :
874 : case EPT_f64:
875 0 : return "f64";
876 :
877 : case EPT_c64:
878 0 : return "c64";
879 :
880 : case EPT_c128:
881 0 : return "c128";
882 :
883 : default:
884 0 : return "unknown";
885 : }
886 : }
887 :
888 : /************************************************************************/
889 : /* HFAGetMapInfo() */
890 : /************************************************************************/
891 :
892 652 : const Eprj_MapInfo *HFAGetMapInfo( HFAHandle hHFA )
893 :
894 : {
895 : HFAEntry *poMIEntry;
896 : Eprj_MapInfo *psMapInfo;
897 :
898 652 : if( hHFA->nBands < 1 )
899 0 : return NULL;
900 :
901 : /* -------------------------------------------------------------------- */
902 : /* Do we already have it? */
903 : /* -------------------------------------------------------------------- */
904 652 : if( hHFA->pMapInfo != NULL )
905 62 : return( (Eprj_MapInfo *) hHFA->pMapInfo );
906 :
907 : /* -------------------------------------------------------------------- */
908 : /* Get the HFA node. If we don't find it under the usual name */
909 : /* we search for any node of the right type (#3338). */
910 : /* -------------------------------------------------------------------- */
911 590 : poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Map_Info" );
912 590 : if( poMIEntry == NULL )
913 : {
914 : HFAEntry *poChild;
915 1472 : for( poChild = hHFA->papoBand[0]->poNode->GetChild();
916 : poChild != NULL && poMIEntry == NULL;
917 : poChild = poChild->GetNext() )
918 : {
919 1042 : if( EQUAL(poChild->GetType(),"Eprj_MapInfo") )
920 0 : poMIEntry = poChild;
921 : }
922 : }
923 :
924 590 : if( poMIEntry == NULL )
925 : {
926 430 : return NULL;
927 : }
928 :
929 : /* -------------------------------------------------------------------- */
930 : /* Allocate the structure. */
931 : /* -------------------------------------------------------------------- */
932 160 : psMapInfo = (Eprj_MapInfo *) CPLCalloc(sizeof(Eprj_MapInfo),1);
933 :
934 : /* -------------------------------------------------------------------- */
935 : /* Fetch the fields. */
936 : /* -------------------------------------------------------------------- */
937 : CPLErr eErr;
938 :
939 160 : psMapInfo->proName = CPLStrdup(poMIEntry->GetStringField("proName"));
940 :
941 : psMapInfo->upperLeftCenter.x =
942 160 : poMIEntry->GetDoubleField("upperLeftCenter.x");
943 : psMapInfo->upperLeftCenter.y =
944 160 : poMIEntry->GetDoubleField("upperLeftCenter.y");
945 :
946 : psMapInfo->lowerRightCenter.x =
947 160 : poMIEntry->GetDoubleField("lowerRightCenter.x");
948 : psMapInfo->lowerRightCenter.y =
949 160 : poMIEntry->GetDoubleField("lowerRightCenter.y");
950 :
951 : psMapInfo->pixelSize.width =
952 160 : poMIEntry->GetDoubleField("pixelSize.width",&eErr);
953 : psMapInfo->pixelSize.height =
954 160 : poMIEntry->GetDoubleField("pixelSize.height",&eErr);
955 :
956 : // The following is basically a hack to get files with
957 : // non-standard MapInfo's that misname the pixelSize fields. (#3338)
958 160 : if( eErr != CE_None )
959 : {
960 : psMapInfo->pixelSize.width =
961 0 : poMIEntry->GetDoubleField("pixelSize.x");
962 : psMapInfo->pixelSize.height =
963 0 : poMIEntry->GetDoubleField("pixelSize.y");
964 : }
965 :
966 160 : psMapInfo->units = CPLStrdup(poMIEntry->GetStringField("units"));
967 :
968 160 : hHFA->pMapInfo = (void *) psMapInfo;
969 :
970 160 : return psMapInfo;
971 : }
972 :
973 : /************************************************************************/
974 : /* HFAInvGeoTransform() */
975 : /************************************************************************/
976 :
977 6 : static int HFAInvGeoTransform( double *gt_in, double *gt_out )
978 :
979 : {
980 : double det, inv_det;
981 :
982 : /* we assume a 3rd row that is [1 0 0] */
983 :
984 : /* Compute determinate */
985 :
986 6 : det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4];
987 :
988 6 : if( fabs(det) < 0.000000000000001 )
989 0 : return 0;
990 :
991 6 : inv_det = 1.0 / det;
992 :
993 : /* compute adjoint, and devide by determinate */
994 :
995 6 : gt_out[1] = gt_in[5] * inv_det;
996 6 : gt_out[4] = -gt_in[4] * inv_det;
997 :
998 6 : gt_out[2] = -gt_in[2] * inv_det;
999 6 : gt_out[5] = gt_in[1] * inv_det;
1000 :
1001 6 : gt_out[0] = ( gt_in[2] * gt_in[3] - gt_in[0] * gt_in[5]) * inv_det;
1002 6 : gt_out[3] = (-gt_in[1] * gt_in[3] + gt_in[0] * gt_in[4]) * inv_det;
1003 :
1004 6 : return 1;
1005 : }
1006 :
1007 : /************************************************************************/
1008 : /* HFAGetGeoTransform() */
1009 : /************************************************************************/
1010 :
1011 376 : int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
1012 :
1013 : {
1014 376 : const Eprj_MapInfo *psMapInfo = HFAGetMapInfo( hHFA );
1015 :
1016 376 : padfGeoTransform[0] = 0.0;
1017 376 : padfGeoTransform[1] = 1.0;
1018 376 : padfGeoTransform[2] = 0.0;
1019 376 : padfGeoTransform[3] = 0.0;
1020 376 : padfGeoTransform[4] = 0.0;
1021 376 : padfGeoTransform[5] = 1.0;
1022 :
1023 : /* -------------------------------------------------------------------- */
1024 : /* Simple (north up) MapInfo approach. */
1025 : /* -------------------------------------------------------------------- */
1026 376 : if( psMapInfo != NULL )
1027 : {
1028 : padfGeoTransform[0] = psMapInfo->upperLeftCenter.x
1029 160 : - psMapInfo->pixelSize.width*0.5;
1030 160 : padfGeoTransform[1] = psMapInfo->pixelSize.width;
1031 160 : if(padfGeoTransform[1] == 0.0)
1032 0 : padfGeoTransform[1] = 1.0;
1033 160 : padfGeoTransform[2] = 0.0;
1034 160 : if( psMapInfo->upperLeftCenter.y >= psMapInfo->lowerRightCenter.y )
1035 160 : padfGeoTransform[5] = - psMapInfo->pixelSize.height;
1036 : else
1037 0 : padfGeoTransform[5] = psMapInfo->pixelSize.height;
1038 160 : if(padfGeoTransform[5] == 0.0)
1039 0 : padfGeoTransform[5] = 1.0;
1040 :
1041 160 : padfGeoTransform[3] = psMapInfo->upperLeftCenter.y
1042 160 : - padfGeoTransform[5]*0.5;
1043 160 : padfGeoTransform[4] = 0.0;
1044 :
1045 : // special logic to fixup odd angular units.
1046 160 : if( EQUAL(psMapInfo->units,"ds") )
1047 : {
1048 0 : padfGeoTransform[0] /= 3600.0;
1049 0 : padfGeoTransform[1] /= 3600.0;
1050 0 : padfGeoTransform[2] /= 3600.0;
1051 0 : padfGeoTransform[3] /= 3600.0;
1052 0 : padfGeoTransform[4] /= 3600.0;
1053 0 : padfGeoTransform[5] /= 3600.0;
1054 : }
1055 :
1056 160 : return TRUE;
1057 : }
1058 :
1059 : /* -------------------------------------------------------------------- */
1060 : /* Try for a MapToPixelXForm affine polynomial supporting */
1061 : /* rotated and sheared affine transformations. */
1062 : /* -------------------------------------------------------------------- */
1063 216 : if( hHFA->nBands == 0 )
1064 0 : return FALSE;
1065 :
1066 : HFAEntry *poXForm0 =
1067 216 : hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
1068 :
1069 216 : if( poXForm0 == NULL )
1070 210 : return FALSE;
1071 :
1072 6 : if( poXForm0->GetIntField( "order" ) != 1
1073 : || poXForm0->GetIntField( "numdimtransform" ) != 2
1074 : || poXForm0->GetIntField( "numdimpolynomial" ) != 2
1075 : || poXForm0->GetIntField( "termcount" ) != 3 )
1076 1 : return FALSE;
1077 :
1078 : // Verify that there aren't any further xform steps.
1079 5 : if( hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm1" )
1080 : != NULL )
1081 1 : return FALSE;
1082 :
1083 : // we should check that the exponent list is 0 0 1 0 0 1 but
1084 : // we don't because we are lazy
1085 :
1086 : // fetch geotransform values.
1087 : double adfXForm[6];
1088 :
1089 4 : adfXForm[0] = poXForm0->GetDoubleField( "polycoefvector[0]" );
1090 4 : adfXForm[1] = poXForm0->GetDoubleField( "polycoefmtx[0]" );
1091 4 : adfXForm[4] = poXForm0->GetDoubleField( "polycoefmtx[1]" );
1092 4 : adfXForm[3] = poXForm0->GetDoubleField( "polycoefvector[1]" );
1093 4 : adfXForm[2] = poXForm0->GetDoubleField( "polycoefmtx[2]" );
1094 4 : adfXForm[5] = poXForm0->GetDoubleField( "polycoefmtx[3]" );
1095 :
1096 : // invert
1097 :
1098 4 : HFAInvGeoTransform( adfXForm, padfGeoTransform );
1099 :
1100 : // Adjust origin from center of top left pixel to top left corner
1101 : // of top left pixel.
1102 :
1103 4 : padfGeoTransform[0] -= padfGeoTransform[1] * 0.5;
1104 4 : padfGeoTransform[0] -= padfGeoTransform[2] * 0.5;
1105 4 : padfGeoTransform[3] -= padfGeoTransform[4] * 0.5;
1106 4 : padfGeoTransform[3] -= padfGeoTransform[5] * 0.5;
1107 :
1108 4 : return TRUE;
1109 : }
1110 :
1111 : /************************************************************************/
1112 : /* HFASetMapInfo() */
1113 : /************************************************************************/
1114 :
1115 91 : CPLErr HFASetMapInfo( HFAHandle hHFA, const Eprj_MapInfo *poMapInfo )
1116 :
1117 : {
1118 : /* -------------------------------------------------------------------- */
1119 : /* Loop over bands, setting information on each one. */
1120 : /* -------------------------------------------------------------------- */
1121 218 : for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
1122 : {
1123 : HFAEntry *poMIEntry;
1124 :
1125 : /* -------------------------------------------------------------------- */
1126 : /* Create a new Map_Info if there isn't one present already. */
1127 : /* -------------------------------------------------------------------- */
1128 127 : poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild( "Map_Info" );
1129 127 : if( poMIEntry == NULL )
1130 : {
1131 : poMIEntry = new HFAEntry( hHFA, "Map_Info", "Eprj_MapInfo",
1132 127 : hHFA->papoBand[iBand]->poNode );
1133 : }
1134 :
1135 127 : poMIEntry->MarkDirty();
1136 :
1137 : /* -------------------------------------------------------------------- */
1138 : /* Ensure we have enough space for all the data. */
1139 : /* -------------------------------------------------------------------- */
1140 : int nSize;
1141 : GByte *pabyData;
1142 :
1143 : nSize = 48 + 40
1144 : + strlen(poMapInfo->proName) + 1
1145 127 : + strlen(poMapInfo->units) + 1;
1146 :
1147 127 : pabyData = poMIEntry->MakeData( nSize );
1148 127 : memset( pabyData, 0, nSize );
1149 :
1150 127 : poMIEntry->SetPosition();
1151 :
1152 : /* -------------------------------------------------------------------- */
1153 : /* Write the various fields. */
1154 : /* -------------------------------------------------------------------- */
1155 127 : poMIEntry->SetStringField( "proName", poMapInfo->proName );
1156 :
1157 : poMIEntry->SetDoubleField( "upperLeftCenter.x",
1158 127 : poMapInfo->upperLeftCenter.x );
1159 : poMIEntry->SetDoubleField( "upperLeftCenter.y",
1160 127 : poMapInfo->upperLeftCenter.y );
1161 :
1162 : poMIEntry->SetDoubleField( "lowerRightCenter.x",
1163 127 : poMapInfo->lowerRightCenter.x );
1164 : poMIEntry->SetDoubleField( "lowerRightCenter.y",
1165 127 : poMapInfo->lowerRightCenter.y );
1166 :
1167 : poMIEntry->SetDoubleField( "pixelSize.width",
1168 127 : poMapInfo->pixelSize.width );
1169 : poMIEntry->SetDoubleField( "pixelSize.height",
1170 127 : poMapInfo->pixelSize.height );
1171 :
1172 127 : poMIEntry->SetStringField( "units", poMapInfo->units );
1173 : }
1174 :
1175 91 : return CE_None;
1176 : }
1177 :
1178 : /************************************************************************/
1179 : /* HFAGetPEString() */
1180 : /* */
1181 : /* Some files have a ProjectionX node contining the ESRI style */
1182 : /* PE_STRING. This function allows fetching from it. */
1183 : /************************************************************************/
1184 :
1185 376 : char *HFAGetPEString( HFAHandle hHFA )
1186 :
1187 : {
1188 376 : if( hHFA->nBands == 0 )
1189 0 : return NULL;
1190 :
1191 : /* -------------------------------------------------------------------- */
1192 : /* Get the HFA node. */
1193 : /* -------------------------------------------------------------------- */
1194 : HFAEntry *poProX;
1195 :
1196 376 : poProX = hHFA->papoBand[0]->poNode->GetNamedChild( "ProjectionX" );
1197 376 : if( poProX == NULL )
1198 276 : return NULL;
1199 :
1200 100 : const char *pszType = poProX->GetStringField( "projection.type.string" );
1201 100 : if( pszType == NULL || !EQUAL(pszType,"PE_COORDSYS") )
1202 0 : return NULL;
1203 :
1204 : /* -------------------------------------------------------------------- */
1205 : /* Use a gross hack to scan ahead to the actual projection */
1206 : /* string. We do it this way because we don't have general */
1207 : /* handling for MIFObjects. */
1208 : /* -------------------------------------------------------------------- */
1209 100 : GByte *pabyData = poProX->GetData();
1210 100 : int nDataSize = poProX->GetDataSize();
1211 :
1212 9400 : while( nDataSize > 10
1213 : && !EQUALN((const char *) pabyData,"PE_COORDSYS,.",13) ) {
1214 9200 : pabyData++;
1215 9200 : nDataSize--;
1216 : }
1217 :
1218 100 : if( nDataSize < 31 )
1219 0 : return NULL;
1220 :
1221 : /* -------------------------------------------------------------------- */
1222 : /* Skip ahead to the actual string. */
1223 : /* -------------------------------------------------------------------- */
1224 100 : pabyData += 30;
1225 100 : nDataSize -= 30;
1226 :
1227 100 : return CPLStrdup( (const char *) pabyData );
1228 : }
1229 :
1230 : /************************************************************************/
1231 : /* HFASetPEString() */
1232 : /************************************************************************/
1233 :
1234 80 : CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
1235 :
1236 : {
1237 : /* -------------------------------------------------------------------- */
1238 : /* Loop over bands, setting information on each one. */
1239 : /* -------------------------------------------------------------------- */
1240 : int iBand;
1241 :
1242 196 : for( iBand = 0; iBand < hHFA->nBands; iBand++ )
1243 : {
1244 : HFAEntry *poProX;
1245 :
1246 : /* -------------------------------------------------------------------- */
1247 : /* Verify we don't already have the node, since update-in-place */
1248 : /* is likely to be more complicated. */
1249 : /* -------------------------------------------------------------------- */
1250 116 : poProX = hHFA->papoBand[iBand]->poNode->GetNamedChild( "ProjectionX" );
1251 :
1252 : /* -------------------------------------------------------------------- */
1253 : /* If we are setting an empty string then a missing entry is */
1254 : /* equivelent. */
1255 : /* -------------------------------------------------------------------- */
1256 116 : if( strlen(pszPEString) == 0 && poProX == NULL )
1257 0 : continue;
1258 :
1259 : /* -------------------------------------------------------------------- */
1260 : /* Create the node. */
1261 : /* -------------------------------------------------------------------- */
1262 116 : if( poProX == NULL )
1263 : {
1264 : poProX = new HFAEntry( hHFA, "ProjectionX","Eprj_MapProjection842",
1265 116 : hHFA->papoBand[iBand]->poNode );
1266 232 : if( poProX == NULL || poProX->GetTypeObject() == NULL )
1267 0 : return CE_Failure;
1268 : }
1269 :
1270 : /* -------------------------------------------------------------------- */
1271 : /* Prepare the data area with some extra space just in case. */
1272 : /* -------------------------------------------------------------------- */
1273 116 : GByte *pabyData = poProX->MakeData( 700 + strlen(pszPEString) );
1274 116 : if( !pabyData )
1275 0 : return CE_Failure;
1276 :
1277 116 : memset( pabyData, 0, 250+strlen(pszPEString) );
1278 :
1279 116 : poProX->SetPosition();
1280 :
1281 116 : poProX->SetStringField( "projection.type.string", "PE_COORDSYS" );
1282 : poProX->SetStringField( "projection.MIFDictionary.string",
1283 116 : "{0:pcstring,}Emif_String,{1:x{0:pcstring,}Emif_String,coordSys,}PE_COORDSYS,." );
1284 :
1285 : /* -------------------------------------------------------------------- */
1286 : /* Use a gross hack to scan ahead to the actual projection */
1287 : /* string. We do it this way because we don't have general */
1288 : /* handling for MIFObjects. */
1289 : /* -------------------------------------------------------------------- */
1290 116 : pabyData = poProX->GetData();
1291 116 : int nDataSize = poProX->GetDataSize();
1292 116 : GUInt32 iOffset = poProX->GetDataPos();
1293 : GUInt32 nSize;
1294 :
1295 10904 : while( nDataSize > 10
1296 : && !EQUALN((const char *) pabyData,"PE_COORDSYS,.",13) ) {
1297 10672 : pabyData++;
1298 10672 : nDataSize--;
1299 10672 : iOffset++;
1300 : }
1301 :
1302 116 : CPLAssert( nDataSize > (int) strlen(pszPEString) + 10 );
1303 :
1304 116 : pabyData += 14;
1305 116 : iOffset += 14;
1306 :
1307 : /* -------------------------------------------------------------------- */
1308 : /* Set the size and offset of the mifobject. */
1309 : /* -------------------------------------------------------------------- */
1310 116 : iOffset += 8;
1311 :
1312 116 : nSize = strlen(pszPEString) + 9;
1313 :
1314 : HFAStandard( 4, &nSize );
1315 116 : memcpy( pabyData, &nSize, 4 );
1316 116 : pabyData += 4;
1317 :
1318 : HFAStandard( 4, &iOffset );
1319 116 : memcpy( pabyData, &iOffset, 4 );
1320 116 : pabyData += 4;
1321 :
1322 : /* -------------------------------------------------------------------- */
1323 : /* Set the size and offset of the string value. */
1324 : /* -------------------------------------------------------------------- */
1325 116 : nSize = strlen(pszPEString) + 1;
1326 :
1327 : HFAStandard( 4, &nSize );
1328 116 : memcpy( pabyData, &nSize, 4 );
1329 116 : pabyData += 4;
1330 :
1331 116 : iOffset = 8;
1332 : HFAStandard( 4, &iOffset );
1333 116 : memcpy( pabyData, &iOffset, 4 );
1334 116 : pabyData += 4;
1335 :
1336 : /* -------------------------------------------------------------------- */
1337 : /* Place the string itself. */
1338 : /* -------------------------------------------------------------------- */
1339 116 : memcpy( pabyData, pszPEString, strlen(pszPEString)+1 );
1340 :
1341 116 : poProX->SetStringField( "title.string", "PE" );
1342 : }
1343 :
1344 80 : return CE_None;
1345 : }
1346 :
1347 : /************************************************************************/
1348 : /* HFAGetProParameters() */
1349 : /************************************************************************/
1350 :
1351 276 : const Eprj_ProParameters *HFAGetProParameters( HFAHandle hHFA )
1352 :
1353 : {
1354 : HFAEntry *poMIEntry;
1355 : Eprj_ProParameters *psProParms;
1356 : int i;
1357 :
1358 276 : if( hHFA->nBands < 1 )
1359 0 : return NULL;
1360 :
1361 : /* -------------------------------------------------------------------- */
1362 : /* Do we already have it? */
1363 : /* -------------------------------------------------------------------- */
1364 276 : if( hHFA->pProParameters != NULL )
1365 0 : return( (Eprj_ProParameters *) hHFA->pProParameters );
1366 :
1367 : /* -------------------------------------------------------------------- */
1368 : /* Get the HFA node. */
1369 : /* -------------------------------------------------------------------- */
1370 276 : poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Projection" );
1371 276 : if( poMIEntry == NULL )
1372 238 : return NULL;
1373 :
1374 : /* -------------------------------------------------------------------- */
1375 : /* Allocate the structure. */
1376 : /* -------------------------------------------------------------------- */
1377 38 : psProParms = (Eprj_ProParameters *)CPLCalloc(sizeof(Eprj_ProParameters),1);
1378 :
1379 : /* -------------------------------------------------------------------- */
1380 : /* Fetch the fields. */
1381 : /* -------------------------------------------------------------------- */
1382 38 : psProParms->proType = (Eprj_ProType) poMIEntry->GetIntField("proType");
1383 38 : psProParms->proNumber = poMIEntry->GetIntField("proNumber");
1384 38 : psProParms->proExeName =CPLStrdup(poMIEntry->GetStringField("proExeName"));
1385 38 : psProParms->proName = CPLStrdup(poMIEntry->GetStringField("proName"));
1386 38 : psProParms->proZone = poMIEntry->GetIntField("proZone");
1387 :
1388 608 : for( i = 0; i < 15; i++ )
1389 : {
1390 : char szFieldName[40];
1391 :
1392 570 : sprintf( szFieldName, "proParams[%d]", i );
1393 570 : psProParms->proParams[i] = poMIEntry->GetDoubleField(szFieldName);
1394 : }
1395 :
1396 : psProParms->proSpheroid.sphereName =
1397 38 : CPLStrdup(poMIEntry->GetStringField("proSpheroid.sphereName"));
1398 38 : psProParms->proSpheroid.a = poMIEntry->GetDoubleField("proSpheroid.a");
1399 38 : psProParms->proSpheroid.b = poMIEntry->GetDoubleField("proSpheroid.b");
1400 : psProParms->proSpheroid.eSquared =
1401 38 : poMIEntry->GetDoubleField("proSpheroid.eSquared");
1402 : psProParms->proSpheroid.radius =
1403 38 : poMIEntry->GetDoubleField("proSpheroid.radius");
1404 :
1405 38 : hHFA->pProParameters = (void *) psProParms;
1406 :
1407 38 : return psProParms;
1408 : }
1409 :
1410 : /************************************************************************/
1411 : /* HFASetProParameters() */
1412 : /************************************************************************/
1413 :
1414 68 : CPLErr HFASetProParameters( HFAHandle hHFA, const Eprj_ProParameters *poPro )
1415 :
1416 : {
1417 : /* -------------------------------------------------------------------- */
1418 : /* Loop over bands, setting information on each one. */
1419 : /* -------------------------------------------------------------------- */
1420 172 : for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
1421 : {
1422 : HFAEntry *poMIEntry;
1423 :
1424 : /* -------------------------------------------------------------------- */
1425 : /* Create a new Projection if there isn't one present already. */
1426 : /* -------------------------------------------------------------------- */
1427 104 : poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
1428 104 : if( poMIEntry == NULL )
1429 : {
1430 : poMIEntry = new HFAEntry( hHFA, "Projection","Eprj_ProParameters",
1431 104 : hHFA->papoBand[iBand]->poNode );
1432 : }
1433 :
1434 104 : poMIEntry->MarkDirty();
1435 :
1436 : /* -------------------------------------------------------------------- */
1437 : /* Ensure we have enough space for all the data. */
1438 : /* -------------------------------------------------------------------- */
1439 : int nSize;
1440 : GByte *pabyData;
1441 :
1442 : nSize = 34 + 15 * 8
1443 : + 8 + strlen(poPro->proName) + 1
1444 104 : + 32 + 8 + strlen(poPro->proSpheroid.sphereName) + 1;
1445 :
1446 104 : if( poPro->proExeName != NULL )
1447 1 : nSize += strlen(poPro->proExeName) + 1;
1448 :
1449 104 : pabyData = poMIEntry->MakeData( nSize );
1450 104 : if(!pabyData)
1451 0 : return CE_Failure;
1452 :
1453 104 : poMIEntry->SetPosition();
1454 :
1455 : // Initialize the whole thing to zeros for a clean start.
1456 104 : memset( poMIEntry->GetData(), 0, poMIEntry->GetDataSize() );
1457 :
1458 : /* -------------------------------------------------------------------- */
1459 : /* Write the various fields. */
1460 : /* -------------------------------------------------------------------- */
1461 104 : poMIEntry->SetIntField( "proType", poPro->proType );
1462 :
1463 104 : poMIEntry->SetIntField( "proNumber", poPro->proNumber );
1464 :
1465 104 : poMIEntry->SetStringField( "proExeName", poPro->proExeName );
1466 104 : poMIEntry->SetStringField( "proName", poPro->proName );
1467 104 : poMIEntry->SetIntField( "proZone", poPro->proZone );
1468 104 : poMIEntry->SetDoubleField( "proParams[0]", poPro->proParams[0] );
1469 104 : poMIEntry->SetDoubleField( "proParams[1]", poPro->proParams[1] );
1470 104 : poMIEntry->SetDoubleField( "proParams[2]", poPro->proParams[2] );
1471 104 : poMIEntry->SetDoubleField( "proParams[3]", poPro->proParams[3] );
1472 104 : poMIEntry->SetDoubleField( "proParams[4]", poPro->proParams[4] );
1473 104 : poMIEntry->SetDoubleField( "proParams[5]", poPro->proParams[5] );
1474 104 : poMIEntry->SetDoubleField( "proParams[6]", poPro->proParams[6] );
1475 104 : poMIEntry->SetDoubleField( "proParams[7]", poPro->proParams[7] );
1476 104 : poMIEntry->SetDoubleField( "proParams[8]", poPro->proParams[8] );
1477 104 : poMIEntry->SetDoubleField( "proParams[9]", poPro->proParams[9] );
1478 104 : poMIEntry->SetDoubleField( "proParams[10]", poPro->proParams[10] );
1479 104 : poMIEntry->SetDoubleField( "proParams[11]", poPro->proParams[11] );
1480 104 : poMIEntry->SetDoubleField( "proParams[12]", poPro->proParams[12] );
1481 104 : poMIEntry->SetDoubleField( "proParams[13]", poPro->proParams[13] );
1482 104 : poMIEntry->SetDoubleField( "proParams[14]", poPro->proParams[14] );
1483 : poMIEntry->SetStringField( "proSpheroid.sphereName",
1484 104 : poPro->proSpheroid.sphereName );
1485 : poMIEntry->SetDoubleField( "proSpheroid.a",
1486 104 : poPro->proSpheroid.a );
1487 : poMIEntry->SetDoubleField( "proSpheroid.b",
1488 104 : poPro->proSpheroid.b );
1489 : poMIEntry->SetDoubleField( "proSpheroid.eSquared",
1490 104 : poPro->proSpheroid.eSquared );
1491 : poMIEntry->SetDoubleField( "proSpheroid.radius",
1492 104 : poPro->proSpheroid.radius );
1493 : }
1494 :
1495 68 : return CE_None;
1496 : }
1497 :
1498 : /************************************************************************/
1499 : /* HFAGetDatum() */
1500 : /************************************************************************/
1501 :
1502 276 : const Eprj_Datum *HFAGetDatum( HFAHandle hHFA )
1503 :
1504 : {
1505 : HFAEntry *poMIEntry;
1506 : Eprj_Datum *psDatum;
1507 : int i;
1508 :
1509 276 : if( hHFA->nBands < 1 )
1510 0 : return NULL;
1511 :
1512 : /* -------------------------------------------------------------------- */
1513 : /* Do we already have it? */
1514 : /* -------------------------------------------------------------------- */
1515 276 : if( hHFA->pDatum != NULL )
1516 0 : return( (Eprj_Datum *) hHFA->pDatum );
1517 :
1518 : /* -------------------------------------------------------------------- */
1519 : /* Get the HFA node. */
1520 : /* -------------------------------------------------------------------- */
1521 276 : poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Projection.Datum" );
1522 276 : if( poMIEntry == NULL )
1523 238 : return NULL;
1524 :
1525 : /* -------------------------------------------------------------------- */
1526 : /* Allocate the structure. */
1527 : /* -------------------------------------------------------------------- */
1528 38 : psDatum = (Eprj_Datum *) CPLCalloc(sizeof(Eprj_Datum),1);
1529 :
1530 : /* -------------------------------------------------------------------- */
1531 : /* Fetch the fields. */
1532 : /* -------------------------------------------------------------------- */
1533 38 : psDatum->datumname = CPLStrdup(poMIEntry->GetStringField("datumname"));
1534 38 : psDatum->type = (Eprj_DatumType) poMIEntry->GetIntField("type");
1535 :
1536 304 : for( i = 0; i < 7; i++ )
1537 : {
1538 : char szFieldName[30];
1539 :
1540 266 : sprintf( szFieldName, "params[%d]", i );
1541 266 : psDatum->params[i] = poMIEntry->GetDoubleField(szFieldName);
1542 : }
1543 :
1544 38 : psDatum->gridname = CPLStrdup(poMIEntry->GetStringField("gridname"));
1545 :
1546 38 : hHFA->pDatum = (void *) psDatum;
1547 :
1548 38 : return psDatum;
1549 : }
1550 :
1551 : /************************************************************************/
1552 : /* HFASetDatum() */
1553 : /************************************************************************/
1554 :
1555 68 : CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
1556 :
1557 : {
1558 : /* -------------------------------------------------------------------- */
1559 : /* Loop over bands, setting information on each one. */
1560 : /* -------------------------------------------------------------------- */
1561 172 : for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
1562 : {
1563 104 : HFAEntry *poDatumEntry=NULL, *poProParms;
1564 :
1565 : /* -------------------------------------------------------------------- */
1566 : /* Create a new Projection if there isn't one present already. */
1567 : /* -------------------------------------------------------------------- */
1568 : poProParms =
1569 104 : hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
1570 104 : if( poProParms == NULL )
1571 : {
1572 : CPLError( CE_Failure, CPLE_AppDefined,
1573 0 : "Can't add Eprj_Datum with no Eprj_ProjParameters." );
1574 0 : return CE_Failure;
1575 : }
1576 :
1577 104 : poDatumEntry = poProParms->GetNamedChild("Datum");
1578 104 : if( poDatumEntry == NULL )
1579 : {
1580 : poDatumEntry = new HFAEntry( hHFA, "Datum","Eprj_Datum",
1581 104 : poProParms );
1582 : }
1583 :
1584 104 : poDatumEntry->MarkDirty();
1585 :
1586 : /* -------------------------------------------------------------------- */
1587 : /* Ensure we have enough space for all the data. */
1588 : /* -------------------------------------------------------------------- */
1589 : int nSize;
1590 : GByte *pabyData;
1591 :
1592 104 : nSize = 26 + strlen(poDatum->datumname) + 1 + 7*8;
1593 :
1594 104 : if( poDatum->gridname != NULL )
1595 23 : nSize += strlen(poDatum->gridname) + 1;
1596 :
1597 104 : pabyData = poDatumEntry->MakeData( nSize );
1598 104 : if(!pabyData)
1599 0 : return CE_Failure;
1600 :
1601 104 : poDatumEntry->SetPosition();
1602 :
1603 : // Initialize the whole thing to zeros for a clean start.
1604 104 : memset( poDatumEntry->GetData(), 0, poDatumEntry->GetDataSize() );
1605 :
1606 : /* -------------------------------------------------------------------- */
1607 : /* Write the various fields. */
1608 : /* -------------------------------------------------------------------- */
1609 104 : poDatumEntry->SetStringField( "datumname", poDatum->datumname );
1610 104 : poDatumEntry->SetIntField( "type", poDatum->type );
1611 :
1612 104 : poDatumEntry->SetDoubleField( "params[0]", poDatum->params[0] );
1613 104 : poDatumEntry->SetDoubleField( "params[1]", poDatum->params[1] );
1614 104 : poDatumEntry->SetDoubleField( "params[2]", poDatum->params[2] );
1615 104 : poDatumEntry->SetDoubleField( "params[3]", poDatum->params[3] );
1616 104 : poDatumEntry->SetDoubleField( "params[4]", poDatum->params[4] );
1617 104 : poDatumEntry->SetDoubleField( "params[5]", poDatum->params[5] );
1618 104 : poDatumEntry->SetDoubleField( "params[6]", poDatum->params[6] );
1619 :
1620 104 : poDatumEntry->SetStringField( "gridname", poDatum->gridname );
1621 : }
1622 :
1623 68 : return CE_None;
1624 : }
1625 :
1626 : /************************************************************************/
1627 : /* HFAGetPCT() */
1628 : /* */
1629 : /* Read the PCT from a band, if it has one. */
1630 : /************************************************************************/
1631 :
1632 450 : CPLErr HFAGetPCT( HFAHandle hHFA, int nBand, int *pnColors,
1633 : double **ppadfRed, double **ppadfGreen,
1634 : double **ppadfBlue , double **ppadfAlpha,
1635 : double **ppadfBins )
1636 :
1637 : {
1638 450 : if( nBand < 1 || nBand > hHFA->nBands )
1639 0 : return CE_Failure;
1640 :
1641 450 : return( hHFA->papoBand[nBand-1]->GetPCT( pnColors, ppadfRed,
1642 : ppadfGreen, ppadfBlue,
1643 900 : ppadfAlpha, ppadfBins ) );
1644 : }
1645 :
1646 : /************************************************************************/
1647 : /* HFASetPCT() */
1648 : /* */
1649 : /* Set the PCT on a band. */
1650 : /************************************************************************/
1651 :
1652 3 : CPLErr HFASetPCT( HFAHandle hHFA, int nBand, int nColors,
1653 : double *padfRed, double *padfGreen, double *padfBlue,
1654 : double *padfAlpha )
1655 :
1656 : {
1657 3 : if( nBand < 1 || nBand > hHFA->nBands )
1658 0 : return CE_Failure;
1659 :
1660 3 : return( hHFA->papoBand[nBand-1]->SetPCT( nColors, padfRed,
1661 6 : padfGreen, padfBlue, padfAlpha ) );
1662 : }
1663 :
1664 : /************************************************************************/
1665 : /* HFAGetDataRange() */
1666 : /************************************************************************/
1667 :
1668 0 : CPLErr HFAGetDataRange( HFAHandle hHFA, int nBand,
1669 : double * pdfMin, double *pdfMax )
1670 :
1671 : {
1672 : HFAEntry *poBinInfo;
1673 :
1674 0 : if( nBand < 1 || nBand > hHFA->nBands )
1675 0 : return CE_Failure;
1676 :
1677 0 : poBinInfo = hHFA->papoBand[nBand-1]->poNode->GetNamedChild("Statistics" );
1678 :
1679 0 : if( poBinInfo == NULL )
1680 0 : return( CE_Failure );
1681 :
1682 0 : *pdfMin = poBinInfo->GetDoubleField( "minimum" );
1683 0 : *pdfMax = poBinInfo->GetDoubleField( "maximum" );
1684 :
1685 0 : if( *pdfMax > *pdfMin )
1686 0 : return CE_None;
1687 : else
1688 0 : return CE_Failure;
1689 : }
1690 :
1691 : /************************************************************************/
1692 : /* HFADumpNode() */
1693 : /************************************************************************/
1694 :
1695 0 : static void HFADumpNode( HFAEntry *poEntry, int nIndent, int bVerbose,
1696 : FILE * fp )
1697 :
1698 : {
1699 : static char szSpaces[256];
1700 : int i;
1701 :
1702 0 : for( i = 0; i < nIndent*2; i++ )
1703 0 : szSpaces[i] = ' ';
1704 0 : szSpaces[nIndent*2] = '\0';
1705 :
1706 : fprintf( fp, "%s%s(%s) @ %d + %d @ %d\n", szSpaces,
1707 : poEntry->GetName(), poEntry->GetType(),
1708 : poEntry->GetFilePos(),
1709 0 : poEntry->GetDataSize(), poEntry->GetDataPos() );
1710 :
1711 0 : if( bVerbose )
1712 : {
1713 0 : strcat( szSpaces, "+ " );
1714 0 : poEntry->DumpFieldValues( fp, szSpaces );
1715 0 : fprintf( fp, "\n" );
1716 : }
1717 :
1718 0 : if( poEntry->GetChild() != NULL )
1719 0 : HFADumpNode( poEntry->GetChild(), nIndent+1, bVerbose, fp );
1720 :
1721 0 : if( poEntry->GetNext() != NULL )
1722 0 : HFADumpNode( poEntry->GetNext(), nIndent, bVerbose, fp );
1723 0 : }
1724 :
1725 : /************************************************************************/
1726 : /* HFADumpTree() */
1727 : /* */
1728 : /* Dump the tree of information in a HFA file. */
1729 : /************************************************************************/
1730 :
1731 0 : void HFADumpTree( HFAHandle hHFA, FILE * fpOut )
1732 :
1733 : {
1734 0 : HFADumpNode( hHFA->poRoot, 0, TRUE, fpOut );
1735 0 : }
1736 :
1737 : /************************************************************************/
1738 : /* HFADumpDictionary() */
1739 : /* */
1740 : /* Dump the dictionary (in raw, and parsed form) to the named */
1741 : /* device. */
1742 : /************************************************************************/
1743 :
1744 0 : void HFADumpDictionary( HFAHandle hHFA, FILE * fpOut )
1745 :
1746 : {
1747 0 : fprintf( fpOut, "%s\n", hHFA->pszDictionary );
1748 :
1749 0 : hHFA->poDictionary->Dump( fpOut );
1750 0 : }
1751 :
1752 : /************************************************************************/
1753 : /* HFAStandard() */
1754 : /* */
1755 : /* Swap byte order on MSB systems. */
1756 : /************************************************************************/
1757 :
1758 : #ifdef CPL_MSB
1759 : void HFAStandard( int nBytes, void * pData )
1760 :
1761 : {
1762 : int i;
1763 : GByte *pabyData = (GByte *) pData;
1764 :
1765 : for( i = nBytes/2-1; i >= 0; i-- )
1766 : {
1767 : GByte byTemp;
1768 :
1769 : byTemp = pabyData[i];
1770 : pabyData[i] = pabyData[nBytes-i-1];
1771 : pabyData[nBytes-i-1] = byTemp;
1772 : }
1773 : }
1774 : #endif
1775 :
1776 : /* ==================================================================== */
1777 : /* Default data dictionary. Emitted verbatim into the imagine */
1778 : /* file. */
1779 : /* ==================================================================== */
1780 :
1781 : static const char *aszDefaultDD[] = {
1782 : "{1:lversion,1:LfreeList,1:LrootEntryPtr,1:sentryHeaderLength,1:LdictionaryPtr,}Ehfa_File,{1:Lnext,1:Lprev,1:Lparent,1:Lchild,1:Ldata,1:ldataSize,64:cname,32:ctype,1:tmodTime,}Ehfa_Entry,{16:clabel,1:LheaderPtr,}Ehfa_HeaderTag,{1:LfreeList,1:lfreeSize,}Ehfa_FreeListNode,{1:lsize,1:Lptr,}Ehfa_Data,{1:lwidth,1:lheight,1:e3:thematic,athematic,fft of real-valued data,layerType,",
1783 : "1:e13:u1,u2,u4,u8,s8,u16,s16,u32,s32,f32,f64,c64,c128,pixelType,1:lblockWidth,1:lblockHeight,}Eimg_Layer,{1:lwidth,1:lheight,1:e3:thematic,athematic,fft of real-valued data,layerType,1:e13:u1,u2,u4,u8,s8,u16,s16,u32,s32,f32,f64,c64,c128,pixelType,1:lblockWidth,1:lblockHeight,}Eimg_Layer_SubSample,{1:e2:raster,vector,type,1:LdictionaryPtr,}Ehfa_Layer,{1:LspaceUsedForRasterData,}ImgFormatInfo831,{1:sfileCode,1:Loffset,1:lsize,1:e2:false,true,logvalid,",
1784 : "1:e2:no compression,ESRI GRID compression,compressionType,}Edms_VirtualBlockInfo,{1:lmin,1:lmax,}Edms_FreeIDList,{1:lnumvirtualblocks,1:lnumobjectsperblock,1:lnextobjectnum,1:e2:no compression,RLC compression,compressionType,0:poEdms_VirtualBlockInfo,blockinfo,0:poEdms_FreeIDList,freelist,1:tmodTime,}Edms_State,{0:pcstring,}Emif_String,{1:oEmif_String,fileName,2:LlayerStackValidFlagsOffset,2:LlayerStackDataOffset,1:LlayerStackCount,1:LlayerStackIndex,}ImgExternalRaster,{1:oEmif_String,algorithm,0:poEmif_String,nameList,}Eimg_RRDNamesList,{1:oEmif_String,projection,1:oEmif_String,units,}Eimg_MapInformation,",
1785 : "{1:oEmif_String,dependent,}Eimg_DependentFile,{1:oEmif_String,ImageLayerName,}Eimg_DependentLayerName,{1:lnumrows,1:lnumcolumns,1:e13:EGDA_TYPE_U1,EGDA_TYPE_U2,EGDA_TYPE_U4,EGDA_TYPE_U8,EGDA_TYPE_S8,EGDA_TYPE_U16,EGDA_TYPE_S16,EGDA_TYPE_U32,EGDA_TYPE_S32,EGDA_TYPE_F32,EGDA_TYPE_F64,EGDA_TYPE_C64,EGDA_TYPE_C128,datatype,1:e4:EGDA_SCALAR_OBJECT,EGDA_TABLE_OBJECT,EGDA_MATRIX_OBJECT,EGDA_RASTER_OBJECT,objecttype,}Egda_BaseData,{1:*bvalueBD,}Eimg_NonInitializedValue,{1:dx,1:dy,}Eprj_Coordinate,{1:dwidth,1:dheight,}Eprj_Size,{0:pcproName,1:*oEprj_Coordinate,upperLeftCenter,",
1786 : "1:*oEprj_Coordinate,lowerRightCenter,1:*oEprj_Size,pixelSize,0:pcunits,}Eprj_MapInfo,{0:pcdatumname,1:e3:EPRJ_DATUM_PARAMETRIC,EPRJ_DATUM_GRID,EPRJ_DATUM_REGRESSION,type,0:pdparams,0:pcgridname,}Eprj_Datum,{0:pcsphereName,1:da,1:db,1:deSquared,1:dradius,}Eprj_Spheroid,{1:e2:EPRJ_INTERNAL,EPRJ_EXTERNAL,proType,1:lproNumber,0:pcproExeName,0:pcproName,1:lproZone,0:pdproParams,1:*oEprj_Spheroid,proSpheroid,}Eprj_ProParameters,{1:dminimum,1:dmaximum,1:dmean,1:dmedian,1:dmode,1:dstddev,}Esta_Statistics,{1:lnumBins,1:e4:direct,linear,logarithmic,explicit,binFunctionType,1:dminLimit,1:dmaxLimit,1:*bbinLimits,}Edsc_BinFunction,{0:poEmif_String,LayerNames,1:*bExcludedValues,1:oEmif_String,AOIname,",
1787 : "1:lSkipFactorX,1:lSkipFactorY,1:*oEdsc_BinFunction,BinFunction,}Eimg_StatisticsParameters830,{1:lnumrows,}Edsc_Table,{1:lnumRows,1:LcolumnDataPtr,1:e4:integer,real,complex,string,dataType,1:lmaxNumChars,}Edsc_Column,{1:lposition,0:pcname,1:e2:EMSC_FALSE,EMSC_TRUE,editable,1:e3:LEFT,CENTER,RIGHT,alignment,0:pcformat,1:e3:DEFAULT,APPLY,AUTO-APPLY,formulamode,0:pcformula,1:dcolumnwidth,0:pcunits,1:e5:NO_COLOR,RED,GREEN,BLUE,COLOR,colorflag,0:pcgreenname,0:pcbluename,}Eded_ColumnAttributes_1,{1:lversion,1:lnumobjects,1:e2:EAOI_UNION,EAOI_INTERSECTION,operation,}Eaoi_AreaOfInterest,",
1788 : "{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,MIFDictionary,0:pCMIFObject,}Emif_MIFObject,",
1789 : "{1:x{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,MIFDictionary,0:pCMIFObject,}Emif_MIFObject,projection,1:x{0:pcstring,}Emif_String,title,}Eprj_MapProjection842,",
1790 : "{0:poEmif_String,titleList,}Exfr_GenericXFormHeader,{1:lorder,1:lnumdimtransform,1:lnumdimpolynomial,1:ltermcount,0:plexponentlist,1:*bpolycoefmtx,1:*bpolycoefvector,}Efga_Polynomial,",
1791 : ".",
1792 : NULL
1793 : };
1794 :
1795 :
1796 :
1797 : /************************************************************************/
1798 : /* HFACreateLL() */
1799 : /* */
1800 : /* Low level creation of an Imagine file. Writes out the */
1801 : /* Ehfa_HeaderTag, dictionary and Ehfa_File. */
1802 : /************************************************************************/
1803 :
1804 131 : HFAHandle HFACreateLL( const char * pszFilename )
1805 :
1806 : {
1807 : VSILFILE *fp;
1808 : HFAInfo_t *psInfo;
1809 :
1810 : /* -------------------------------------------------------------------- */
1811 : /* Create the file in the file system. */
1812 : /* -------------------------------------------------------------------- */
1813 131 : fp = VSIFOpenL( pszFilename, "w+b" );
1814 131 : if( fp == NULL )
1815 : {
1816 : CPLError( CE_Failure, CPLE_OpenFailed,
1817 : "Creation of file %s failed.",
1818 2 : pszFilename );
1819 2 : return NULL;
1820 : }
1821 :
1822 : /* -------------------------------------------------------------------- */
1823 : /* Create the HFAInfo_t */
1824 : /* -------------------------------------------------------------------- */
1825 129 : psInfo = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
1826 :
1827 129 : psInfo->fp = fp;
1828 129 : psInfo->eAccess = HFA_Update;
1829 129 : psInfo->nXSize = 0;
1830 129 : psInfo->nYSize = 0;
1831 129 : psInfo->nBands = 0;
1832 129 : psInfo->papoBand = NULL;
1833 129 : psInfo->pMapInfo = NULL;
1834 129 : psInfo->pDatum = NULL;
1835 129 : psInfo->pProParameters = NULL;
1836 129 : psInfo->bTreeDirty = FALSE;
1837 129 : psInfo->pszFilename = CPLStrdup(CPLGetFilename(pszFilename));
1838 129 : psInfo->pszPath = CPLStrdup(CPLGetPath(pszFilename));
1839 :
1840 : /* -------------------------------------------------------------------- */
1841 : /* Write out the Ehfa_HeaderTag */
1842 : /* -------------------------------------------------------------------- */
1843 : GInt32 nHeaderPos;
1844 :
1845 129 : VSIFWriteL( (void *) "EHFA_HEADER_TAG", 1, 16, fp );
1846 :
1847 129 : nHeaderPos = 20;
1848 : HFAStandard( 4, &nHeaderPos );
1849 129 : VSIFWriteL( &nHeaderPos, 4, 1, fp );
1850 :
1851 : /* -------------------------------------------------------------------- */
1852 : /* Write the Ehfa_File node, locked in at offset 20. */
1853 : /* -------------------------------------------------------------------- */
1854 129 : GInt32 nVersion = 1, nFreeList = 0, nRootEntry = 0;
1855 129 : GInt16 nEntryHeaderLength = 128;
1856 129 : GInt32 nDictionaryPtr = 38;
1857 :
1858 129 : psInfo->nEntryHeaderLength = nEntryHeaderLength;
1859 129 : psInfo->nRootPos = 0;
1860 129 : psInfo->nDictionaryPos = nDictionaryPtr;
1861 129 : psInfo->nVersion = nVersion;
1862 :
1863 : HFAStandard( 4, &nVersion );
1864 : HFAStandard( 4, &nFreeList );
1865 : HFAStandard( 4, &nRootEntry );
1866 : HFAStandard( 2, &nEntryHeaderLength );
1867 : HFAStandard( 4, &nDictionaryPtr );
1868 :
1869 129 : VSIFWriteL( &nVersion, 4, 1, fp );
1870 129 : VSIFWriteL( &nFreeList, 4, 1, fp );
1871 129 : VSIFWriteL( &nRootEntry, 4, 1, fp );
1872 129 : VSIFWriteL( &nEntryHeaderLength, 2, 1, fp );
1873 129 : VSIFWriteL( &nDictionaryPtr, 4, 1, fp );
1874 :
1875 : /* -------------------------------------------------------------------- */
1876 : /* Write the dictionary, locked in at location 38. Note that */
1877 : /* we jump through a bunch of hoops to operate on the */
1878 : /* dictionary in chunks because some compiles (such as VC++) */
1879 : /* don't allow particularly large static strings. */
1880 : /* -------------------------------------------------------------------- */
1881 129 : int nDictLen = 0, iChunk;
1882 :
1883 1419 : for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
1884 1290 : nDictLen += strlen(aszDefaultDD[iChunk]);
1885 :
1886 129 : psInfo->pszDictionary = (char *) CPLMalloc(nDictLen+1);
1887 129 : psInfo->pszDictionary[0] = '\0';
1888 :
1889 1419 : for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
1890 1290 : strcat( psInfo->pszDictionary, aszDefaultDD[iChunk] );
1891 :
1892 : VSIFWriteL( (void *) psInfo->pszDictionary, 1,
1893 129 : strlen(psInfo->pszDictionary)+1, fp );
1894 :
1895 129 : psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary );
1896 :
1897 129 : psInfo->nEndOfFile = (GUInt32) VSIFTellL( fp );
1898 :
1899 : /* -------------------------------------------------------------------- */
1900 : /* Create a root entry. */
1901 : /* -------------------------------------------------------------------- */
1902 258 : psInfo->poRoot = new HFAEntry( psInfo, "root", "root", NULL );
1903 :
1904 : /* -------------------------------------------------------------------- */
1905 : /* If an .ige or .rrd file exists with the same base name, */
1906 : /* delete them. (#1784) */
1907 : /* -------------------------------------------------------------------- */
1908 129 : CPLString osExtension = CPLGetExtension(pszFilename);
1909 258 : if( !EQUAL(osExtension,"rrd") && !EQUAL(osExtension,"aux") )
1910 : {
1911 126 : CPLString osPath = CPLGetPath( pszFilename );
1912 126 : CPLString osBasename = CPLGetBasename( pszFilename );
1913 : VSIStatBufL sStatBuf;
1914 126 : CPLString osSupFile = CPLFormCIFilename( osPath, osBasename, "rrd" );
1915 :
1916 126 : if( VSIStatL( osSupFile, &sStatBuf ) == 0 )
1917 0 : VSIUnlink( osSupFile );
1918 :
1919 126 : osSupFile = CPLFormCIFilename( osPath, osBasename, "ige" );
1920 :
1921 126 : if( VSIStatL( osSupFile, &sStatBuf ) == 0 )
1922 0 : VSIUnlink( osSupFile );
1923 : }
1924 :
1925 129 : return psInfo;
1926 : }
1927 :
1928 : /************************************************************************/
1929 : /* HFAAllocateSpace() */
1930 : /* */
1931 : /* Return an area in the file to the caller to write the */
1932 : /* requested number of bytes. Currently this is always at the */
1933 : /* end of the file, but eventually we might actually keep track */
1934 : /* of free space. The HFAInfo_t's concept of file size is */
1935 : /* updated, even if nothing ever gets written to this region. */
1936 : /* */
1937 : /* Returns the offset to the requested space, or zero one */
1938 : /* failure. */
1939 : /************************************************************************/
1940 :
1941 2045 : GUInt32 HFAAllocateSpace( HFAInfo_t *psInfo, GUInt32 nBytes )
1942 :
1943 : {
1944 : /* should check if this will wrap over 2GB limit */
1945 :
1946 2045 : psInfo->nEndOfFile += nBytes;
1947 2045 : return psInfo->nEndOfFile - nBytes;
1948 : }
1949 :
1950 : /************************************************************************/
1951 : /* HFAFlush() */
1952 : /* */
1953 : /* Write out any dirty tree information to disk, putting the */
1954 : /* disk file in a consistent state. */
1955 : /************************************************************************/
1956 :
1957 263 : CPLErr HFAFlush( HFAHandle hHFA )
1958 :
1959 : {
1960 : CPLErr eErr;
1961 :
1962 263 : if( !hHFA->bTreeDirty && !hHFA->poDictionary->bDictionaryTextDirty )
1963 0 : return CE_None;
1964 :
1965 263 : CPLAssert( hHFA->poRoot != NULL );
1966 :
1967 : /* -------------------------------------------------------------------- */
1968 : /* Flush HFAEntry tree to disk. */
1969 : /* -------------------------------------------------------------------- */
1970 263 : if( hHFA->bTreeDirty )
1971 : {
1972 263 : eErr = hHFA->poRoot->FlushToDisk();
1973 263 : if( eErr != CE_None )
1974 0 : return eErr;
1975 :
1976 263 : hHFA->bTreeDirty = FALSE;
1977 : }
1978 :
1979 : /* -------------------------------------------------------------------- */
1980 : /* Flush Dictionary to disk. */
1981 : /* -------------------------------------------------------------------- */
1982 263 : GUInt32 nNewDictionaryPos = hHFA->nDictionaryPos;
1983 :
1984 263 : if( hHFA->poDictionary->bDictionaryTextDirty )
1985 : {
1986 0 : VSIFSeekL( hHFA->fp, 0, SEEK_END );
1987 0 : nNewDictionaryPos = (GUInt32) VSIFTellL( hHFA->fp );
1988 : VSIFWriteL( hHFA->poDictionary->osDictionaryText.c_str(),
1989 : strlen(hHFA->poDictionary->osDictionaryText.c_str()) + 1,
1990 0 : 1, hHFA->fp );
1991 0 : hHFA->poDictionary->bDictionaryTextDirty = FALSE;
1992 : }
1993 :
1994 : /* -------------------------------------------------------------------- */
1995 : /* do we need to update the Ehfa_File pointer to the root node? */
1996 : /* -------------------------------------------------------------------- */
1997 263 : if( hHFA->nRootPos != hHFA->poRoot->GetFilePos()
1998 : || nNewDictionaryPos != hHFA->nDictionaryPos )
1999 : {
2000 : GUInt32 nOffset;
2001 : GUInt32 nHeaderPos;
2002 :
2003 129 : VSIFSeekL( hHFA->fp, 16, SEEK_SET );
2004 129 : VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, hHFA->fp );
2005 : HFAStandard( 4, &nHeaderPos );
2006 :
2007 129 : nOffset = hHFA->nRootPos = hHFA->poRoot->GetFilePos();
2008 : HFAStandard( 4, &nOffset );
2009 129 : VSIFSeekL( hHFA->fp, nHeaderPos+8, SEEK_SET );
2010 129 : VSIFWriteL( &nOffset, 4, 1, hHFA->fp );
2011 :
2012 129 : nOffset = hHFA->nDictionaryPos = nNewDictionaryPos;
2013 : HFAStandard( 4, &nOffset );
2014 129 : VSIFSeekL( hHFA->fp, nHeaderPos+14, SEEK_SET );
2015 129 : VSIFWriteL( &nOffset, 4, 1, hHFA->fp );
2016 : }
2017 :
2018 263 : return CE_None;
2019 : }
2020 :
2021 : /************************************************************************/
2022 : /* HFACreateLayer() */
2023 : /* */
2024 : /* Create a layer object, and corresponding RasterDMS. */
2025 : /* Suitable for use with primary layers, and overviews. */
2026 : /************************************************************************/
2027 :
2028 : int
2029 169 : HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
2030 : const char *pszLayerName,
2031 : int bOverview, int nBlockSize,
2032 : int bCreateCompressed, int bCreateLargeRaster,
2033 : int bDependentLayer,
2034 : int nXSize, int nYSize, int nDataType,
2035 : char **papszOptions,
2036 :
2037 : // these are only related to external (large) files
2038 : GIntBig nStackValidFlagsOffset,
2039 : GIntBig nStackDataOffset,
2040 : int nStackCount, int nStackIndex )
2041 :
2042 : {
2043 :
2044 : HFAEntry *poEimg_Layer;
2045 : const char *pszLayerType;
2046 :
2047 169 : if( bOverview )
2048 7 : pszLayerType = "Eimg_Layer_SubSample";
2049 : else
2050 162 : pszLayerType = "Eimg_Layer";
2051 :
2052 169 : if (nBlockSize <= 0)
2053 : {
2054 0 : CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateLayer : nBlockXSize < 0");
2055 0 : return FALSE;
2056 : }
2057 :
2058 : /* -------------------------------------------------------------------- */
2059 : /* Work out some details about the tiling scheme. */
2060 : /* -------------------------------------------------------------------- */
2061 : int nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
2062 :
2063 169 : nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
2064 169 : nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
2065 169 : nBlocks = nBlocksPerRow * nBlocksPerColumn;
2066 : nBytesPerBlock = (nBlockSize * nBlockSize
2067 169 : * HFAGetDataTypeBits(nDataType) + 7) / 8;
2068 :
2069 : /* -------------------------------------------------------------------- */
2070 : /* Create the Eimg_Layer for the band. */
2071 : /* -------------------------------------------------------------------- */
2072 : poEimg_Layer =
2073 169 : new HFAEntry( psInfo, pszLayerName, pszLayerType, poParent );
2074 :
2075 169 : poEimg_Layer->SetIntField( "width", nXSize );
2076 169 : poEimg_Layer->SetIntField( "height", nYSize );
2077 169 : poEimg_Layer->SetStringField( "layerType", "athematic" );
2078 169 : poEimg_Layer->SetIntField( "pixelType", nDataType );
2079 169 : poEimg_Layer->SetIntField( "blockWidth", nBlockSize );
2080 169 : poEimg_Layer->SetIntField( "blockHeight", nBlockSize );
2081 :
2082 : /* -------------------------------------------------------------------- */
2083 : /* Create the RasterDMS (block list). This is a complex type */
2084 : /* with pointers, and variable size. We set the superstructure */
2085 : /* ourselves rather than trying to have the HFA type management */
2086 : /* system do it for us (since this would be hard to implement). */
2087 : /* -------------------------------------------------------------------- */
2088 491 : if ( !bCreateLargeRaster && !bDependentLayer )
2089 : {
2090 : int nDmsSize;
2091 : HFAEntry *poEdms_State;
2092 : GByte *pabyData;
2093 :
2094 : poEdms_State =
2095 160 : new HFAEntry( psInfo, "RasterDMS", "Edms_State", poEimg_Layer );
2096 :
2097 160 : nDmsSize = 14 * nBlocks + 38;
2098 160 : pabyData = poEdms_State->MakeData( nDmsSize );
2099 :
2100 : /* set some simple values */
2101 160 : poEdms_State->SetIntField( "numvirtualblocks", nBlocks );
2102 : poEdms_State->SetIntField( "numobjectsperblock",
2103 160 : nBlockSize*nBlockSize );
2104 : poEdms_State->SetIntField( "nextobjectnum",
2105 160 : nBlockSize*nBlockSize*nBlocks );
2106 :
2107 : /* Is file compressed or not? */
2108 160 : if( bCreateCompressed )
2109 : {
2110 6 : poEdms_State->SetStringField( "compressionType", "RLC compression" );
2111 : }
2112 : else
2113 : {
2114 154 : poEdms_State->SetStringField( "compressionType", "no compression" );
2115 : }
2116 :
2117 : /* we need to hardcode file offset into the data, so locate it now */
2118 160 : poEdms_State->SetPosition();
2119 :
2120 : /* Set block info headers */
2121 : GUInt32 nValue;
2122 :
2123 : /* blockinfo count */
2124 160 : nValue = nBlocks;
2125 : HFAStandard( 4, &nValue );
2126 160 : memcpy( pabyData + 14, &nValue, 4 );
2127 :
2128 : /* blockinfo position */
2129 160 : nValue = poEdms_State->GetDataPos() + 22;
2130 : HFAStandard( 4, &nValue );
2131 160 : memcpy( pabyData + 18, &nValue, 4 );
2132 :
2133 : /* Set each blockinfo */
2134 572 : for( int iBlock = 0; iBlock < nBlocks; iBlock++ )
2135 : {
2136 : GInt16 nValue16;
2137 412 : int nOffset = 22 + 14 * iBlock;
2138 :
2139 : /* fileCode */
2140 412 : nValue16 = 0;
2141 : HFAStandard( 2, &nValue16 );
2142 412 : memcpy( pabyData + nOffset, &nValue16, 2 );
2143 :
2144 : /* offset */
2145 412 : if( bCreateCompressed )
2146 : {
2147 : /* flag it with zero offset - will allocate space when we compress it */
2148 6 : nValue = 0;
2149 : }
2150 : else
2151 : {
2152 406 : nValue = HFAAllocateSpace( psInfo, nBytesPerBlock );
2153 : }
2154 : HFAStandard( 4, &nValue );
2155 412 : memcpy( pabyData + nOffset + 2, &nValue, 4 );
2156 :
2157 : /* size */
2158 412 : if( bCreateCompressed )
2159 : {
2160 : /* flag it with zero size - don't know until we compress it */
2161 6 : nValue = 0;
2162 : }
2163 : else
2164 : {
2165 406 : nValue = nBytesPerBlock;
2166 : }
2167 : HFAStandard( 4, &nValue );
2168 412 : memcpy( pabyData + nOffset + 6, &nValue, 4 );
2169 :
2170 : /* logValid (false) */
2171 412 : nValue16 = 0;
2172 : HFAStandard( 2, &nValue16 );
2173 412 : memcpy( pabyData + nOffset + 10, &nValue16, 2 );
2174 :
2175 : /* compressionType */
2176 412 : if( bCreateCompressed )
2177 6 : nValue16 = 1;
2178 : else
2179 406 : nValue16 = 0;
2180 :
2181 : HFAStandard( 2, &nValue16 );
2182 412 : memcpy( pabyData + nOffset + 12, &nValue16, 2 );
2183 : }
2184 :
2185 : }
2186 : /* -------------------------------------------------------------------- */
2187 : /* Create ExternalRasterDMS object. */
2188 : /* -------------------------------------------------------------------- */
2189 9 : else if( bCreateLargeRaster )
2190 : {
2191 : HFAEntry *poEdms_State;
2192 :
2193 : poEdms_State =
2194 : new HFAEntry( psInfo, "ExternalRasterDMS",
2195 7 : "ImgExternalRaster", poEimg_Layer );
2196 7 : poEdms_State->MakeData( 8 + strlen(psInfo->pszIGEFilename) + 1 + 6 * 4 );
2197 :
2198 : poEdms_State->SetStringField( "fileName.string",
2199 7 : psInfo->pszIGEFilename );
2200 :
2201 : poEdms_State->SetIntField( "layerStackValidFlagsOffset[0]",
2202 7 : (int) (nStackValidFlagsOffset & 0xFFFFFFFF));
2203 : poEdms_State->SetIntField( "layerStackValidFlagsOffset[1]",
2204 7 : (int) (nStackValidFlagsOffset >> 32) );
2205 :
2206 : poEdms_State->SetIntField( "layerStackDataOffset[0]",
2207 7 : (int) (nStackDataOffset & 0xFFFFFFFF) );
2208 : poEdms_State->SetIntField( "layerStackDataOffset[1]",
2209 7 : (int) (nStackDataOffset >> 32 ) );
2210 7 : poEdms_State->SetIntField( "layerStackCount", nStackCount );
2211 7 : poEdms_State->SetIntField( "layerStackIndex", nStackIndex );
2212 : }
2213 :
2214 : /* -------------------------------------------------------------------- */
2215 : /* Dependent... */
2216 : /* -------------------------------------------------------------------- */
2217 2 : else if( bDependentLayer )
2218 : {
2219 : HFAEntry *poDepLayerName;
2220 :
2221 : poDepLayerName =
2222 : new HFAEntry( psInfo, "DependentLayerName",
2223 2 : "Eimg_DependentLayerName", poEimg_Layer );
2224 2 : poDepLayerName->MakeData( 8 + strlen(pszLayerName) + 2 );
2225 :
2226 : poDepLayerName->SetStringField( "ImageLayerName.string",
2227 2 : pszLayerName );
2228 : }
2229 :
2230 : /* -------------------------------------------------------------------- */
2231 : /* Create the Ehfa_Layer. */
2232 : /* -------------------------------------------------------------------- */
2233 : HFAEntry *poEhfa_Layer;
2234 : GUInt32 nLDict;
2235 : char szLDict[128], chBandType;
2236 :
2237 169 : if( nDataType == EPT_u1 )
2238 2 : chBandType = '1';
2239 167 : else if( nDataType == EPT_u2 )
2240 0 : chBandType = '2';
2241 167 : else if( nDataType == EPT_u4 )
2242 0 : chBandType = '4';
2243 167 : else if( nDataType == EPT_u8 )
2244 86 : chBandType = 'c';
2245 81 : else if( nDataType == EPT_s8 )
2246 0 : chBandType = 'C';
2247 81 : else if( nDataType == EPT_u16 )
2248 13 : chBandType = 's';
2249 68 : else if( nDataType == EPT_s16 )
2250 9 : chBandType = 'S';
2251 59 : else if( nDataType == EPT_u32 )
2252 : // for some reason erdas imagine expects an L for unsinged 32 bit ints
2253 : // otherwise it gives strange "out of memory errors"
2254 9 : chBandType = 'L';
2255 50 : else if( nDataType == EPT_s32 )
2256 11 : chBandType = 'L';
2257 39 : else if( nDataType == EPT_f32 )
2258 9 : chBandType = 'f';
2259 30 : else if( nDataType == EPT_f64 )
2260 12 : chBandType = 'd';
2261 18 : else if( nDataType == EPT_c64 )
2262 9 : chBandType = 'm';
2263 9 : else if( nDataType == EPT_c128 )
2264 9 : chBandType = 'M';
2265 : else
2266 : {
2267 0 : CPLAssert( FALSE );
2268 0 : chBandType = 'c';
2269 : }
2270 :
2271 : // the first value in the entry below gives the number of pixels within a block
2272 169 : sprintf( szLDict, "{%d:%cdata,}RasterDMS,.", nBlockSize*nBlockSize, chBandType );
2273 :
2274 : poEhfa_Layer = new HFAEntry( psInfo, "Ehfa_Layer", "Ehfa_Layer",
2275 169 : poEimg_Layer );
2276 169 : poEhfa_Layer->MakeData();
2277 169 : poEhfa_Layer->SetPosition();
2278 169 : nLDict = HFAAllocateSpace( psInfo, strlen(szLDict) + 1 );
2279 :
2280 169 : poEhfa_Layer->SetStringField( "type", "raster" );
2281 169 : poEhfa_Layer->SetIntField( "dictionaryPtr", nLDict );
2282 :
2283 169 : VSIFSeekL( psInfo->fp, nLDict, SEEK_SET );
2284 169 : VSIFWriteL( (void *) szLDict, strlen(szLDict) + 1, 1, psInfo->fp );
2285 :
2286 169 : return TRUE;
2287 : }
2288 :
2289 :
2290 : /************************************************************************/
2291 : /* HFACreate() */
2292 : /************************************************************************/
2293 :
2294 130 : HFAHandle HFACreate( const char * pszFilename,
2295 : int nXSize, int nYSize, int nBands,
2296 : int nDataType, char ** papszOptions )
2297 :
2298 : {
2299 : HFAHandle psInfo;
2300 130 : int nBlockSize = 64;
2301 130 : const char * pszValue = CSLFetchNameValue( papszOptions, "BLOCKSIZE" );
2302 :
2303 130 : if ( pszValue != NULL )
2304 : {
2305 0 : nBlockSize = atoi( pszValue );
2306 : // check for sane values
2307 0 : if ( ( nBlockSize < 32 ) || (nBlockSize > 2048) )
2308 : {
2309 0 : nBlockSize = 64;
2310 : }
2311 : }
2312 : int bCreateLargeRaster = CSLFetchBoolean(papszOptions,"USE_SPILL",
2313 130 : FALSE);
2314 : int bCreateCompressed =
2315 : CSLFetchBoolean(papszOptions,"COMPRESS", FALSE)
2316 130 : || CSLFetchBoolean(papszOptions,"COMPRESSED", FALSE);
2317 130 : int bCreateAux = CSLFetchBoolean(papszOptions,"AUX", FALSE);
2318 :
2319 130 : char *pszFullFilename = NULL, *pszRawFilename = NULL;
2320 :
2321 : /* -------------------------------------------------------------------- */
2322 : /* Create the low level structure. */
2323 : /* -------------------------------------------------------------------- */
2324 130 : psInfo = HFACreateLL( pszFilename );
2325 130 : if( psInfo == NULL )
2326 2 : return NULL;
2327 :
2328 : /* -------------------------------------------------------------------- */
2329 : /* Create the DependentFile node if requested. */
2330 : /* -------------------------------------------------------------------- */
2331 : const char *pszDependentFile =
2332 128 : CSLFetchNameValue( papszOptions, "DEPENDENT_FILE" );
2333 :
2334 128 : if( pszDependentFile != NULL )
2335 : {
2336 : HFAEntry *poDF = new HFAEntry( psInfo, "DependentFile",
2337 2 : "Eimg_DependentFile", psInfo->poRoot );
2338 :
2339 2 : poDF->MakeData( strlen(pszDependentFile) + 50 );
2340 2 : poDF->SetPosition();
2341 2 : poDF->SetStringField( "dependent.string", pszDependentFile );
2342 : }
2343 :
2344 : /* -------------------------------------------------------------------- */
2345 : /* Work out some details about the tiling scheme. */
2346 : /* -------------------------------------------------------------------- */
2347 : int nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
2348 :
2349 128 : nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
2350 128 : nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
2351 128 : nBlocks = nBlocksPerRow * nBlocksPerColumn;
2352 : nBytesPerBlock = (nBlockSize * nBlockSize
2353 128 : * HFAGetDataTypeBits(nDataType) + 7) / 8;
2354 :
2355 : CPLDebug( "HFACreate", "Blocks per row %d, blocks per column %d, "
2356 : "total number of blocks %d, bytes per block %d.",
2357 128 : nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock );
2358 :
2359 : /* -------------------------------------------------------------------- */
2360 : /* Check whether we should create external large file with */
2361 : /* image. We create a spill file if the amount of imagery is */
2362 : /* close to 2GB. We don't check the amount of auxilary */
2363 : /* information, so in theory if there were an awful lot of */
2364 : /* non-imagery data our approximate size could be smaller than */
2365 : /* the file will actually we be. We leave room for 10MB of */
2366 : /* auxilary data. */
2367 : /* We can also force spill file creation using option */
2368 : /* SPILL_FILE=YES. */
2369 : /* -------------------------------------------------------------------- */
2370 : double dfApproxSize = (double)nBytesPerBlock * (double)nBlocks *
2371 128 : (double)nBands + 10000000.0;
2372 :
2373 128 : if( dfApproxSize > 2147483648.0 && !bCreateAux )
2374 0 : bCreateLargeRaster = TRUE;
2375 :
2376 : // erdas imagine creates this entry even if an external spill file is used
2377 128 : if( !bCreateAux )
2378 : {
2379 : HFAEntry *poImgFormat;
2380 : poImgFormat = new HFAEntry( psInfo, "IMGFormatInfo",
2381 126 : "ImgFormatInfo831", psInfo->poRoot );
2382 126 : poImgFormat->MakeData();
2383 126 : if ( bCreateLargeRaster )
2384 : {
2385 7 : poImgFormat->SetIntField( "spaceUsedForRasterData", 0 );
2386 7 : bCreateCompressed = FALSE; // Can't be compressed if we are creating a spillfile
2387 : }
2388 : else
2389 : {
2390 : poImgFormat->SetIntField( "spaceUsedForRasterData",
2391 119 : nBytesPerBlock*nBlocks*nBands );
2392 : }
2393 : }
2394 :
2395 : /* -------------------------------------------------------------------- */
2396 : /* Create external file and write its header. */
2397 : /* -------------------------------------------------------------------- */
2398 128 : GIntBig nValidFlagsOffset = 0, nDataOffset = 0;
2399 :
2400 128 : if( bCreateLargeRaster )
2401 : {
2402 7 : if( !HFACreateSpillStack( psInfo, nXSize, nYSize, nBands,
2403 : nBlockSize, nDataType,
2404 : &nValidFlagsOffset, &nDataOffset ) )
2405 : {
2406 0 : CPLFree( pszRawFilename );
2407 0 : CPLFree( pszFullFilename );
2408 0 : return NULL;
2409 : }
2410 : }
2411 :
2412 : /* ==================================================================== */
2413 : /* Create each band (layer) */
2414 : /* ==================================================================== */
2415 : int iBand;
2416 :
2417 290 : for( iBand = 0; iBand < nBands; iBand++ )
2418 : {
2419 : char szName[128];
2420 :
2421 162 : sprintf( szName, "Layer_%d", iBand + 1 );
2422 :
2423 162 : if( !HFACreateLayer( psInfo, psInfo->poRoot, szName, FALSE, nBlockSize,
2424 : bCreateCompressed, bCreateLargeRaster, bCreateAux,
2425 : nXSize, nYSize, nDataType, papszOptions,
2426 : nValidFlagsOffset, nDataOffset,
2427 : nBands, iBand ) )
2428 : {
2429 0 : HFAClose( psInfo );
2430 0 : return NULL;
2431 : }
2432 : }
2433 :
2434 : /* -------------------------------------------------------------------- */
2435 : /* Initialize the band information. */
2436 : /* -------------------------------------------------------------------- */
2437 128 : HFAParseBandInfo( psInfo );
2438 :
2439 128 : return psInfo;
2440 : }
2441 :
2442 : /************************************************************************/
2443 : /* HFACreateOverview() */
2444 : /* */
2445 : /* Create an overview layer object for a band. */
2446 : /************************************************************************/
2447 :
2448 7 : int HFACreateOverview( HFAHandle hHFA, int nBand, int nOverviewLevel,
2449 : const char *pszResampling )
2450 :
2451 : {
2452 7 : if( nBand < 1 || nBand > hHFA->nBands )
2453 0 : return -1;
2454 : else
2455 : {
2456 7 : HFABand *poBand = hHFA->papoBand[nBand-1];
2457 7 : return poBand->CreateOverview( nOverviewLevel, pszResampling );
2458 : }
2459 : }
2460 :
2461 : /************************************************************************/
2462 : /* HFAGetMetadata() */
2463 : /* */
2464 : /* Read metadata structured in a table called GDAL_MetaData. */
2465 : /************************************************************************/
2466 :
2467 826 : char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
2468 :
2469 : {
2470 : HFAEntry *poTable;
2471 :
2472 1276 : if( nBand > 0 && nBand <= hHFA->nBands )
2473 450 : poTable = hHFA->papoBand[nBand - 1]->poNode->GetChild();
2474 376 : else if( nBand == 0 )
2475 376 : poTable = hHFA->poRoot->GetChild();
2476 : else
2477 0 : return NULL;
2478 :
2479 826 : for( ; poTable != NULL && !EQUAL(poTable->GetName(),"GDAL_MetaData");
2480 : poTable = poTable->GetNext() ) {}
2481 :
2482 826 : if( poTable == NULL || !EQUAL(poTable->GetType(),"Edsc_Table") )
2483 741 : return NULL;
2484 :
2485 85 : if( poTable->GetIntField( "numRows" ) != 1 )
2486 : {
2487 : CPLDebug( "HFADataset", "GDAL_MetaData.numRows = %d, expected 1!",
2488 0 : poTable->GetIntField( "numRows" ) );
2489 0 : return NULL;
2490 : }
2491 :
2492 : /* -------------------------------------------------------------------- */
2493 : /* Loop over each column. Each column will be one metadata */
2494 : /* entry, with the title being the key, and the row value being */
2495 : /* the value. There is only ever one row in GDAL_MetaData */
2496 : /* tables. */
2497 : /* -------------------------------------------------------------------- */
2498 : HFAEntry *poColumn;
2499 85 : char **papszMD = NULL;
2500 :
2501 257 : for( poColumn = poTable->GetChild();
2502 : poColumn != NULL;
2503 : poColumn = poColumn->GetNext() )
2504 : {
2505 : const char *pszValue;
2506 : int columnDataPtr;
2507 :
2508 : // Skip the #Bin_Function# entry.
2509 172 : if( EQUALN(poColumn->GetName(),"#",1) )
2510 85 : continue;
2511 :
2512 87 : pszValue = poColumn->GetStringField( "dataType" );
2513 87 : if( pszValue == NULL || !EQUAL(pszValue,"string") )
2514 0 : continue;
2515 :
2516 87 : columnDataPtr = poColumn->GetIntField( "columnDataPtr" );
2517 87 : if( columnDataPtr == 0 )
2518 0 : continue;
2519 :
2520 : /* -------------------------------------------------------------------- */
2521 : /* read up to nMaxNumChars bytes from the indicated location. */
2522 : /* allocate required space temporarily */
2523 : /* nMaxNumChars should have been set by GDAL orginally so we should*/
2524 : /* trust it, but who knows... */
2525 : /* -------------------------------------------------------------------- */
2526 87 : int nMaxNumChars = poColumn->GetIntField( "maxNumChars" );
2527 :
2528 87 : if( nMaxNumChars == 0 )
2529 : {
2530 0 : papszMD = CSLSetNameValue( papszMD, poColumn->GetName(), "" );
2531 : }
2532 : else
2533 : {
2534 87 : char *pszMDValue = (char*) VSIMalloc(nMaxNumChars);
2535 87 : if (pszMDValue == NULL)
2536 : {
2537 : CPLError(CE_Failure, CPLE_OutOfMemory,
2538 0 : "HFAGetMetadata : Out of memory while allocating %d bytes", nMaxNumChars);
2539 0 : continue;
2540 : }
2541 :
2542 87 : if( VSIFSeekL( hHFA->fp, columnDataPtr, SEEK_SET ) != 0 )
2543 0 : continue;
2544 :
2545 87 : int nMDBytes = VSIFReadL( pszMDValue, 1, nMaxNumChars, hHFA->fp );
2546 87 : if( nMDBytes == 0 )
2547 : {
2548 0 : CPLFree( pszMDValue );
2549 0 : continue;
2550 : }
2551 :
2552 87 : pszMDValue[nMaxNumChars-1] = '\0';
2553 :
2554 : papszMD = CSLSetNameValue( papszMD, poColumn->GetName(),
2555 87 : pszMDValue );
2556 87 : CPLFree( pszMDValue );
2557 : }
2558 : }
2559 :
2560 85 : return papszMD;
2561 : }
2562 :
2563 : /************************************************************************/
2564 : /* HFASetGDALMetadata() */
2565 : /* */
2566 : /* This function is used to set metadata in a table called */
2567 : /* GDAL_MetaData. It is called by HFASetMetadata() for all */
2568 : /* metadata items that aren't some specific supported */
2569 : /* information (like histogram or stats info). */
2570 : /************************************************************************/
2571 :
2572 : static CPLErr
2573 45 : HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
2574 :
2575 : {
2576 45 : if( papszMD == NULL )
2577 0 : return CE_None;
2578 :
2579 : HFAEntry *poNode;
2580 :
2581 47 : if( nBand > 0 && nBand <= hHFA->nBands )
2582 2 : poNode = hHFA->papoBand[nBand - 1]->poNode;
2583 43 : else if( nBand == 0 )
2584 43 : poNode = hHFA->poRoot;
2585 : else
2586 0 : return CE_Failure;
2587 :
2588 : /* -------------------------------------------------------------------- */
2589 : /* Create the Descriptor table. */
2590 : /* Check we have no table with this name already */
2591 : /* -------------------------------------------------------------------- */
2592 45 : HFAEntry *poEdsc_Table = poNode->GetNamedChild( "GDAL_MetaData" );
2593 :
2594 45 : if( poEdsc_Table == NULL || !EQUAL(poEdsc_Table->GetType(),"Edsc_Table") )
2595 : poEdsc_Table = new HFAEntry( hHFA, "GDAL_MetaData", "Edsc_Table",
2596 44 : poNode );
2597 :
2598 45 : poEdsc_Table->SetIntField( "numrows", 1 );
2599 :
2600 : /* -------------------------------------------------------------------- */
2601 : /* Create the Binning function node. I am not sure that we */
2602 : /* really need this though. */
2603 : /* Check it doesn't exist already */
2604 : /* -------------------------------------------------------------------- */
2605 : HFAEntry *poEdsc_BinFunction =
2606 45 : poEdsc_Table->GetNamedChild( "#Bin_Function#" );
2607 :
2608 45 : if( poEdsc_BinFunction == NULL
2609 : || !EQUAL(poEdsc_BinFunction->GetType(),"Edsc_BinFunction") )
2610 : poEdsc_BinFunction = new HFAEntry( hHFA, "#Bin_Function#",
2611 44 : "Edsc_BinFunction", poEdsc_Table );
2612 :
2613 : // Because of the BaseData we have to hardcode the size.
2614 45 : poEdsc_BinFunction->MakeData( 30 );
2615 :
2616 45 : poEdsc_BinFunction->SetIntField( "numBins", 1 );
2617 45 : poEdsc_BinFunction->SetStringField( "binFunction", "direct" );
2618 45 : poEdsc_BinFunction->SetDoubleField( "minLimit", 0.0 );
2619 45 : poEdsc_BinFunction->SetDoubleField( "maxLimit", 0.0 );
2620 :
2621 : /* -------------------------------------------------------------------- */
2622 : /* Process each metadata item as a separate column. */
2623 : /* -------------------------------------------------------------------- */
2624 91 : for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
2625 : {
2626 : HFAEntry *poEdsc_Column;
2627 46 : char *pszKey = NULL;
2628 : const char *pszValue;
2629 :
2630 46 : pszValue = CPLParseNameValue( papszMD[iColumn], &pszKey );
2631 46 : if( pszValue == NULL )
2632 0 : continue;
2633 :
2634 : /* -------------------------------------------------------------------- */
2635 : /* Create the Edsc_Column. */
2636 : /* Check it doesn't exist already */
2637 : /* -------------------------------------------------------------------- */
2638 46 : poEdsc_Column = poEdsc_Table->GetNamedChild(pszKey);
2639 :
2640 46 : if( poEdsc_Column == NULL
2641 : || !EQUAL(poEdsc_Column->GetType(),"Edsc_Column") )
2642 : poEdsc_Column = new HFAEntry( hHFA, pszKey, "Edsc_Column",
2643 45 : poEdsc_Table );
2644 :
2645 46 : poEdsc_Column->SetIntField( "numRows", 1 );
2646 46 : poEdsc_Column->SetStringField( "dataType", "string" );
2647 46 : poEdsc_Column->SetIntField( "maxNumChars", strlen(pszValue)+1 );
2648 :
2649 : /* -------------------------------------------------------------------- */
2650 : /* Write the data out. */
2651 : /* -------------------------------------------------------------------- */
2652 46 : int nOffset = HFAAllocateSpace( hHFA, strlen(pszValue)+1);
2653 :
2654 46 : poEdsc_Column->SetIntField( "columnDataPtr", nOffset );
2655 :
2656 46 : VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
2657 46 : VSIFWriteL( (void *) pszValue, 1, strlen(pszValue)+1, hHFA->fp );
2658 :
2659 46 : CPLFree( pszKey );
2660 : }
2661 :
2662 45 : return CE_Failure;
2663 : }
2664 :
2665 : /************************************************************************/
2666 : /* HFASetMetadata() */
2667 : /************************************************************************/
2668 :
2669 51 : CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
2670 :
2671 : {
2672 51 : char **papszGDALMD = NULL;
2673 :
2674 51 : if( CSLCount(papszMD) == 0 )
2675 0 : return CE_None;
2676 :
2677 : HFAEntry *poNode;
2678 :
2679 59 : if( nBand > 0 && nBand <= hHFA->nBands )
2680 8 : poNode = hHFA->papoBand[nBand - 1]->poNode;
2681 43 : else if( nBand == 0 )
2682 43 : poNode = hHFA->poRoot;
2683 : else
2684 0 : return CE_Failure;
2685 :
2686 : /* -------------------------------------------------------------------- */
2687 : /* Check if the Metadata is an "known" entity which should be */
2688 : /* stored in a better place. */
2689 : /* -------------------------------------------------------------------- */
2690 51 : char * pszBinValues = NULL;
2691 51 : int bCreatedHistogramParameters = FALSE;
2692 51 : int bCreatedStatistics = FALSE;
2693 51 : const char ** pszAuxMetaData = GetHFAAuxMetaDataList();
2694 : // check each metadata item
2695 153 : for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
2696 : {
2697 102 : char *pszKey = NULL;
2698 : const char *pszValue;
2699 :
2700 102 : pszValue = CPLParseNameValue( papszMD[iColumn], &pszKey );
2701 102 : if( pszValue == NULL )
2702 0 : continue;
2703 :
2704 : // know look if its known
2705 : int i;
2706 1047 : for( i = 0; pszAuxMetaData[i] != NULL; i += 4 )
2707 : {
2708 997 : if ( EQUALN( pszAuxMetaData[i + 2], pszKey, strlen(pszKey) ) )
2709 52 : break;
2710 : }
2711 102 : if ( pszAuxMetaData[i] != NULL )
2712 : {
2713 : // found one, get the right entry
2714 : HFAEntry *poEntry;
2715 :
2716 52 : if( strlen(pszAuxMetaData[i]) > 0 )
2717 47 : poEntry = poNode->GetNamedChild( pszAuxMetaData[i] );
2718 : else
2719 5 : poEntry = poNode;
2720 :
2721 52 : if( poEntry == NULL && strlen(pszAuxMetaData[i+3]) > 0 )
2722 : {
2723 : // child does not yet exist --> create it
2724 : poEntry = new HFAEntry( hHFA, pszAuxMetaData[i], pszAuxMetaData[i+3],
2725 8 : poNode );
2726 :
2727 8 : if ( EQUALN( "Statistics", pszAuxMetaData[i], 10 ) )
2728 4 : bCreatedStatistics = TRUE;
2729 :
2730 8 : if( EQUALN( "HistogramParameters", pszAuxMetaData[i], 19 ) )
2731 : {
2732 : // this is a bit nasty I need to set the string field for the object
2733 : // first because the SetStringField sets the count for the object
2734 : // BinFunction to the length of the string
2735 4 : poEntry->MakeData( 70 );
2736 4 : poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
2737 :
2738 4 : bCreatedHistogramParameters = TRUE;
2739 : }
2740 : }
2741 52 : if ( poEntry == NULL )
2742 : {
2743 9 : CPLFree( pszKey );
2744 9 : continue;
2745 : }
2746 :
2747 43 : const char *pszFieldName = pszAuxMetaData[i+1] + 1;
2748 43 : switch( pszAuxMetaData[i+1][0] )
2749 : {
2750 : case 'd':
2751 : {
2752 34 : double dfValue = atof( pszValue );
2753 34 : poEntry->SetDoubleField( pszFieldName, dfValue );
2754 : }
2755 34 : break;
2756 : case 'i':
2757 : case 'l':
2758 : {
2759 4 : int nValue = atoi( pszValue );
2760 4 : poEntry->SetIntField( pszFieldName, nValue );
2761 : }
2762 4 : break;
2763 : case 's':
2764 : case 'e':
2765 : {
2766 5 : poEntry->SetStringField( pszFieldName, pszValue );
2767 : }
2768 5 : break;
2769 : default:
2770 0 : CPLAssert( FALSE );
2771 : }
2772 : }
2773 50 : else if ( EQUALN( "STATISTICS_HISTOBINVALUES", pszKey, strlen(pszKey) ) )
2774 : {
2775 4 : pszBinValues = strdup( pszValue );
2776 : }
2777 : else
2778 46 : papszGDALMD = CSLAddString( papszGDALMD, papszMD[iColumn] );
2779 :
2780 93 : CPLFree( pszKey );
2781 : }
2782 :
2783 : /* -------------------------------------------------------------------- */
2784 : /* Special case to write out the histogram. */
2785 : /* -------------------------------------------------------------------- */
2786 51 : if ( pszBinValues != NULL )
2787 : {
2788 4 : HFAEntry * poEntry = poNode->GetNamedChild( "HistogramParameters" );
2789 4 : if ( poEntry != NULL && bCreatedHistogramParameters )
2790 : {
2791 : // if this node exists we have added Histogram data -- complete with some defaults
2792 4 : poEntry->SetIntField( "SkipFactorX", 1 );
2793 4 : poEntry->SetIntField( "SkipFactorY", 1 );
2794 :
2795 4 : int nNumBins = poEntry->GetIntField( "BinFunction.numBins" );
2796 4 : double dMinLimit = poEntry->GetDoubleField( "BinFunction.minLimit" );
2797 4 : double dMaxLimit = poEntry->GetDoubleField( "BinFunction.maxLimit" );
2798 :
2799 : // fill the descriptor table - check it isn't there already
2800 4 : poEntry = poNode->GetNamedChild( "Descriptor_Table" );
2801 4 : if( poEntry == NULL || !EQUAL(poEntry->GetType(),"Edsc_Table") )
2802 4 : poEntry = new HFAEntry( hHFA, "Descriptor_Table", "Edsc_Table", poNode );
2803 :
2804 4 : poEntry->SetIntField( "numRows", nNumBins );
2805 :
2806 : // bin function
2807 4 : HFAEntry * poBinFunc = poEntry->GetNamedChild( "#Bin_Function#" );
2808 4 : if( poBinFunc == NULL || !EQUAL(poBinFunc->GetType(),"Edsc_BinFunction") )
2809 4 : poBinFunc = new HFAEntry( hHFA, "#Bin_Function#", "Edsc_BinFunction", poEntry );
2810 :
2811 4 : poBinFunc->MakeData( 30 );
2812 4 : poBinFunc->SetIntField( "numBins", nNumBins );
2813 4 : poBinFunc->SetDoubleField( "minLimit", dMinLimit );
2814 4 : poBinFunc->SetDoubleField( "maxLimit", dMaxLimit );
2815 4 : poBinFunc->SetStringField( "binFunctionType", "linear" ); // we use always a linear
2816 :
2817 : // we need a child named histogram
2818 4 : HFAEntry * poHisto = poEntry->GetNamedChild( "Histogram" );
2819 4 : if( poHisto == NULL || !EQUAL(poHisto->GetType(),"Edsc_Column") )
2820 4 : poHisto = new HFAEntry( hHFA, "Histogram", "Edsc_Column", poEntry );
2821 :
2822 4 : poHisto->SetIntField( "numRows", nNumBins );
2823 : // allocate space for the bin values
2824 4 : GUInt32 nOffset = HFAAllocateSpace( hHFA, nNumBins*4 );
2825 4 : poHisto->SetIntField( "columnDataPtr", nOffset );
2826 4 : poHisto->SetStringField( "dataType", "integer" );
2827 4 : poHisto->SetIntField( "maxNumChars", 0 );
2828 : // write out histogram data
2829 4 : char * pszWork = pszBinValues;
2830 1017 : for ( int nBin = 0; nBin < nNumBins; ++nBin )
2831 : {
2832 1013 : char * pszEnd = strchr( pszWork, '|' );
2833 1013 : if ( pszEnd != NULL )
2834 : {
2835 1013 : *pszEnd = 0;
2836 1013 : VSIFSeekL( hHFA->fp, nOffset + 4*nBin, SEEK_SET );
2837 1013 : int nValue = atoi( pszWork );
2838 : HFAStandard( 4, &nValue );
2839 :
2840 1013 : VSIFWriteL( (void *)&nValue, 1, 4, hHFA->fp );
2841 1013 : pszWork = pszEnd + 1;
2842 : }
2843 : }
2844 : }
2845 4 : free( pszBinValues );
2846 : }
2847 :
2848 : /* -------------------------------------------------------------------- */
2849 : /* If we created a statistics node then try to create a */
2850 : /* StatisticsParameters node too. */
2851 : /* -------------------------------------------------------------------- */
2852 51 : if( bCreatedStatistics )
2853 : {
2854 : HFAEntry *poEntry =
2855 : new HFAEntry( hHFA, "StatisticsParameters",
2856 4 : "Eimg_StatisticsParameters830", poNode );
2857 :
2858 4 : poEntry->MakeData( 70 );
2859 : //poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
2860 :
2861 4 : poEntry->SetIntField( "SkipFactorX", 1 );
2862 4 : poEntry->SetIntField( "SkipFactorY", 1 );
2863 : }
2864 :
2865 : /* -------------------------------------------------------------------- */
2866 : /* Write out metadata items without a special place. */
2867 : /* -------------------------------------------------------------------- */
2868 51 : if( CSLCount( papszGDALMD) != 0 )
2869 : {
2870 45 : CPLErr eErr = HFASetGDALMetadata( hHFA, nBand, papszGDALMD );
2871 :
2872 45 : CSLDestroy( papszGDALMD );
2873 45 : return eErr;
2874 : }
2875 : else
2876 6 : return CE_Failure;
2877 : }
2878 :
2879 : /************************************************************************/
2880 : /* HFAGetIGEFilename() */
2881 : /* */
2882 : /* Returns the .ige filename if one is associated with this */
2883 : /* object. For files not newly created we need to scan the */
2884 : /* bands for spill files. Presumably there will only be one. */
2885 : /* */
2886 : /* NOTE: Returns full path, not just the filename portion. */
2887 : /************************************************************************/
2888 :
2889 127 : const char *HFAGetIGEFilename( HFAHandle hHFA )
2890 :
2891 : {
2892 127 : if( hHFA->pszIGEFilename == NULL )
2893 : {
2894 106 : HFAEntry *poDMS = NULL;
2895 : std::vector<HFAEntry*> apoDMSList =
2896 106 : hHFA->poRoot->FindChildren( NULL, "ImgExternalRaster" );
2897 :
2898 106 : if( apoDMSList.size() > 0 )
2899 31 : poDMS = apoDMSList[0];
2900 :
2901 : /* -------------------------------------------------------------------- */
2902 : /* Get the IGE filename from if we have an ExternalRasterDMS */
2903 : /* -------------------------------------------------------------------- */
2904 106 : if( poDMS )
2905 : {
2906 : const char *pszRawFilename =
2907 31 : poDMS->GetStringField( "fileName.string" );
2908 :
2909 31 : if( pszRawFilename != NULL )
2910 : {
2911 : VSIStatBufL sStatBuf;
2912 : CPLString osFullFilename =
2913 31 : CPLFormFilename( hHFA->pszPath, pszRawFilename, NULL );
2914 :
2915 31 : if( VSIStatL( osFullFilename, &sStatBuf ) != 0 )
2916 : {
2917 0 : CPLString osExtension = CPLGetExtension(pszRawFilename);
2918 0 : CPLString osBasename = CPLGetBasename(hHFA->pszFilename);
2919 : CPLString osFullFilename =
2920 : CPLFormFilename( hHFA->pszPath, osBasename,
2921 0 : osExtension );
2922 :
2923 0 : if( VSIStatL( osFullFilename, &sStatBuf ) == 0 )
2924 : hHFA->pszIGEFilename =
2925 : CPLStrdup(
2926 : CPLFormFilename( NULL, osBasename,
2927 0 : osExtension ) );
2928 : else
2929 0 : hHFA->pszIGEFilename = CPLStrdup( pszRawFilename );
2930 : }
2931 : else
2932 31 : hHFA->pszIGEFilename = CPLStrdup( pszRawFilename );
2933 : }
2934 106 : }
2935 : }
2936 :
2937 : /* -------------------------------------------------------------------- */
2938 : /* Return the full filename. */
2939 : /* -------------------------------------------------------------------- */
2940 127 : if( hHFA->pszIGEFilename )
2941 52 : return CPLFormFilename( hHFA->pszPath, hHFA->pszIGEFilename, NULL );
2942 : else
2943 75 : return NULL;
2944 : }
2945 :
2946 : /************************************************************************/
2947 : /* HFACreateSpillStack() */
2948 : /* */
2949 : /* Create a new stack of raster layers in the spill (.ige) */
2950 : /* file. Create the spill file if it didn't exist before. */
2951 : /************************************************************************/
2952 :
2953 7 : int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
2954 : int nLayers, int nBlockSize, int nDataType,
2955 : GIntBig *pnValidFlagsOffset,
2956 : GIntBig *pnDataOffset )
2957 :
2958 : {
2959 : /* -------------------------------------------------------------------- */
2960 : /* Form .ige filename. */
2961 : /* -------------------------------------------------------------------- */
2962 : char *pszFullFilename;
2963 :
2964 7 : if (nBlockSize <= 0)
2965 : {
2966 0 : CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateSpillStack : nBlockXSize < 0");
2967 0 : return FALSE;
2968 : }
2969 :
2970 7 : if( psInfo->pszIGEFilename == NULL )
2971 : {
2972 7 : if( EQUAL(CPLGetExtension(psInfo->pszFilename),"rrd") )
2973 : psInfo->pszIGEFilename =
2974 0 : CPLStrdup( CPLResetExtension( psInfo->pszFilename, "rde" ) );
2975 7 : else if( EQUAL(CPLGetExtension(psInfo->pszFilename),"aux") )
2976 : psInfo->pszIGEFilename =
2977 0 : CPLStrdup( CPLResetExtension( psInfo->pszFilename, "axe" ) );
2978 : else
2979 : psInfo->pszIGEFilename =
2980 7 : CPLStrdup( CPLResetExtension( psInfo->pszFilename, "ige" ) );
2981 : }
2982 :
2983 : pszFullFilename =
2984 7 : CPLStrdup( CPLFormFilename( psInfo->pszPath, psInfo->pszIGEFilename, NULL ) );
2985 :
2986 : /* -------------------------------------------------------------------- */
2987 : /* Try and open it. If we fail, create it and write the magic */
2988 : /* header. */
2989 : /* -------------------------------------------------------------------- */
2990 : static const char *pszMagick = "ERDAS_IMG_EXTERNAL_RASTER";
2991 : VSILFILE *fpVSIL;
2992 :
2993 7 : fpVSIL = VSIFOpenL( pszFullFilename, "r+b" );
2994 7 : if( fpVSIL == NULL )
2995 : {
2996 7 : fpVSIL = VSIFOpenL( pszFullFilename, "w+" );
2997 7 : if( fpVSIL == NULL )
2998 : {
2999 : CPLError( CE_Failure, CPLE_OpenFailed,
3000 : "Failed to create spill file %s.\n%s",
3001 0 : psInfo->pszIGEFilename, VSIStrerror( errno ) );
3002 0 : return FALSE;
3003 : }
3004 :
3005 7 : VSIFWriteL( (void *) pszMagick, 1, strlen(pszMagick)+1, fpVSIL );
3006 : }
3007 :
3008 7 : CPLFree( pszFullFilename );
3009 :
3010 : /* -------------------------------------------------------------------- */
3011 : /* Work out some details about the tiling scheme. */
3012 : /* -------------------------------------------------------------------- */
3013 : int nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
3014 : int nBytesPerRow, nBlockMapSize, iFlagsSize;
3015 :
3016 7 : nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
3017 7 : nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
3018 7 : nBlocks = nBlocksPerRow * nBlocksPerColumn;
3019 : nBytesPerBlock = (nBlockSize * nBlockSize
3020 7 : * HFAGetDataTypeBits(nDataType) + 7) / 8;
3021 :
3022 7 : nBytesPerRow = ( nBlocksPerRow + 7 ) / 8;
3023 7 : nBlockMapSize = nBytesPerRow * nBlocksPerColumn;
3024 7 : iFlagsSize = nBlockMapSize + 20;
3025 :
3026 : /* -------------------------------------------------------------------- */
3027 : /* Write stack prefix information. */
3028 : /* -------------------------------------------------------------------- */
3029 : GByte bUnknown;
3030 : GInt32 nValue32;
3031 :
3032 7 : VSIFSeekL( fpVSIL, 0, SEEK_END );
3033 :
3034 7 : bUnknown = 1;
3035 7 : VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
3036 7 : nValue32 = nLayers;
3037 : HFAStandard( 4, &nValue32 );
3038 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3039 7 : nValue32 = nXSize;
3040 : HFAStandard( 4, &nValue32 );
3041 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3042 7 : nValue32 = nYSize;
3043 : HFAStandard( 4, &nValue32 );
3044 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3045 7 : nValue32 = nBlockSize;
3046 : HFAStandard( 4, &nValue32 );
3047 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3048 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3049 7 : bUnknown = 3;
3050 7 : VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
3051 7 : bUnknown = 0;
3052 7 : VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
3053 :
3054 : /* -------------------------------------------------------------------- */
3055 : /* Write out ValidFlags section(s). */
3056 : /* -------------------------------------------------------------------- */
3057 : unsigned char *pabyBlockMap;
3058 : int iBand;
3059 :
3060 7 : *pnValidFlagsOffset = VSIFTellL( fpVSIL );
3061 :
3062 7 : pabyBlockMap = (unsigned char *) VSIMalloc( nBlockMapSize );
3063 7 : if (pabyBlockMap == NULL)
3064 : {
3065 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "HFACreateSpillStack : Out of memory");
3066 0 : VSIFCloseL( fpVSIL );
3067 0 : return FALSE;
3068 : }
3069 :
3070 7 : memset( pabyBlockMap, 0xff, nBlockMapSize );
3071 14 : for ( iBand = 0; iBand < nLayers; iBand++ )
3072 : {
3073 : int i, iRemainder;
3074 :
3075 7 : nValue32 = 1; // Unknown
3076 : HFAStandard( 4, &nValue32 );
3077 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3078 7 : nValue32 = 0; // Unknown
3079 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3080 7 : nValue32 = nBlocksPerColumn;
3081 : HFAStandard( 4, &nValue32 );
3082 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3083 7 : nValue32 = nBlocksPerRow;
3084 : HFAStandard( 4, &nValue32 );
3085 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3086 7 : nValue32 = 0x30000; // Unknown
3087 : HFAStandard( 4, &nValue32 );
3088 7 : VSIFWriteL( &nValue32, 4, 1, fpVSIL );
3089 :
3090 7 : iRemainder = nBlocksPerRow % 8;
3091 : CPLDebug( "HFACreate",
3092 : "Block map size %d, bytes per row %d, remainder %d.",
3093 7 : nBlockMapSize, nBytesPerRow, iRemainder );
3094 7 : if ( iRemainder )
3095 : {
3096 14 : for ( i = nBytesPerRow - 1; i < nBlockMapSize; i+=nBytesPerRow )
3097 7 : pabyBlockMap[i] = (GByte) ((1<<iRemainder) - 1);
3098 : }
3099 :
3100 7 : VSIFWriteL( pabyBlockMap, 1, nBlockMapSize, fpVSIL );
3101 : }
3102 7 : CPLFree(pabyBlockMap);
3103 7 : pabyBlockMap = NULL;
3104 :
3105 : /* -------------------------------------------------------------------- */
3106 : /* Extend the file to account for all the imagery space. */
3107 : /* -------------------------------------------------------------------- */
3108 : GIntBig nTileDataSize = ((GIntBig) nBytesPerBlock)
3109 7 : * nBlocksPerRow * nBlocksPerColumn * nLayers;
3110 :
3111 7 : *pnDataOffset = VSIFTellL( fpVSIL );
3112 :
3113 7 : if( VSIFSeekL( fpVSIL, nTileDataSize - 1 + *pnDataOffset, SEEK_SET ) != 0
3114 : || VSIFWriteL( (void *) "", 1, 1, fpVSIL ) != 1 )
3115 : {
3116 : CPLError( CE_Failure, CPLE_FileIO,
3117 : "Failed to extend %s to full size (%g bytes),\n"
3118 : "likely out of disk space.\n%s",
3119 : psInfo->pszIGEFilename,
3120 : (double) nTileDataSize - 1 + *pnDataOffset,
3121 0 : VSIStrerror( errno ) );
3122 :
3123 0 : VSIFCloseL( fpVSIL );
3124 0 : return FALSE;
3125 : }
3126 :
3127 7 : VSIFCloseL( fpVSIL );
3128 :
3129 7 : return TRUE;
3130 : }
3131 :
3132 : /************************************************************************/
3133 : /* HFAReadAndValidatePoly() */
3134 : /************************************************************************/
3135 :
3136 3 : static int HFAReadAndValidatePoly( HFAEntry *poTarget,
3137 : const char *pszName,
3138 : Efga_Polynomial *psRetPoly )
3139 :
3140 : {
3141 3 : CPLString osFldName;
3142 :
3143 3 : memset( psRetPoly, 0, sizeof(Efga_Polynomial) );
3144 :
3145 3 : osFldName.Printf( "%sorder", pszName );
3146 3 : psRetPoly->order = poTarget->GetIntField(osFldName);
3147 :
3148 3 : if( psRetPoly->order < 1 || psRetPoly->order > 3 )
3149 0 : return FALSE;
3150 :
3151 : /* -------------------------------------------------------------------- */
3152 : /* Validate that things are in a "well known" form. */
3153 : /* -------------------------------------------------------------------- */
3154 : int numdimtransform, numdimpolynomial, termcount;
3155 :
3156 3 : osFldName.Printf( "%snumdimtransform", pszName );
3157 3 : numdimtransform = poTarget->GetIntField(osFldName);
3158 :
3159 3 : osFldName.Printf( "%snumdimpolynomial", pszName );
3160 3 : numdimpolynomial = poTarget->GetIntField(osFldName);
3161 :
3162 3 : osFldName.Printf( "%stermcount", pszName );
3163 3 : termcount = poTarget->GetIntField(osFldName);
3164 :
3165 3 : if( numdimtransform != 2 || numdimpolynomial != 2 )
3166 0 : return FALSE;
3167 :
3168 3 : if( (psRetPoly->order == 1 && termcount != 3)
3169 : || (psRetPoly->order == 2 && termcount != 6)
3170 : || (psRetPoly->order == 3 && termcount != 10) )
3171 0 : return FALSE;
3172 :
3173 : // we don't check the exponent organization for now. Hopefully
3174 : // it is always standard.
3175 :
3176 : /* -------------------------------------------------------------------- */
3177 : /* Get coefficients. */
3178 : /* -------------------------------------------------------------------- */
3179 : int i;
3180 :
3181 43 : for( i = 0; i < termcount*2 - 2; i++ )
3182 : {
3183 40 : osFldName.Printf( "%spolycoefmtx[%d]", pszName, i );
3184 40 : psRetPoly->polycoefmtx[i] = poTarget->GetDoubleField(osFldName);
3185 : }
3186 :
3187 9 : for( i = 0; i < 2; i++ )
3188 : {
3189 6 : osFldName.Printf( "%spolycoefvector[%d]", pszName, i );
3190 6 : psRetPoly->polycoefvector[i] = poTarget->GetDoubleField(osFldName);
3191 : }
3192 :
3193 3 : return TRUE;
3194 : }
3195 :
3196 : /************************************************************************/
3197 : /* HFAReadXFormStack() */
3198 : /************************************************************************/
3199 :
3200 :
3201 212 : int HFAReadXFormStack( HFAHandle hHFA,
3202 : Efga_Polynomial **ppasPolyListForward,
3203 : Efga_Polynomial **ppasPolyListReverse )
3204 :
3205 : {
3206 212 : if( hHFA->nBands == 0 )
3207 0 : return 0;
3208 :
3209 : /* -------------------------------------------------------------------- */
3210 : /* Get the HFA node. */
3211 : /* -------------------------------------------------------------------- */
3212 : HFAEntry *poXFormHeader;
3213 :
3214 212 : poXFormHeader = hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm" );
3215 212 : if( poXFormHeader == NULL )
3216 210 : return 0;
3217 :
3218 : /* -------------------------------------------------------------------- */
3219 : /* Loop over children, collecting XForms. */
3220 : /* -------------------------------------------------------------------- */
3221 : HFAEntry *poXForm;
3222 2 : int nStepCount = 0;
3223 2 : *ppasPolyListForward = NULL;
3224 2 : *ppasPolyListReverse = NULL;
3225 :
3226 5 : for( poXForm = poXFormHeader->GetChild();
3227 : poXForm != NULL;
3228 : poXForm = poXForm->GetNext() )
3229 : {
3230 3 : int bSuccess = FALSE;
3231 : Efga_Polynomial sForward, sReverse;
3232 3 : memset( &sForward, 0, sizeof(sForward) );
3233 3 : memset( &sReverse, 0, sizeof(sReverse) );
3234 :
3235 3 : if( EQUAL(poXForm->GetType(),"Efga_Polynomial") )
3236 : {
3237 : bSuccess =
3238 1 : HFAReadAndValidatePoly( poXForm, "", &sForward );
3239 :
3240 1 : if( bSuccess )
3241 : {
3242 : double adfGT[6], adfInvGT[6];
3243 :
3244 1 : adfGT[0] = sForward.polycoefvector[0];
3245 1 : adfGT[1] = sForward.polycoefmtx[0];
3246 1 : adfGT[2] = sForward.polycoefmtx[2];
3247 1 : adfGT[3] = sForward.polycoefvector[1];
3248 1 : adfGT[4] = sForward.polycoefmtx[1];
3249 1 : adfGT[5] = sForward.polycoefmtx[3];
3250 :
3251 1 : bSuccess = HFAInvGeoTransform( adfGT, adfInvGT );
3252 :
3253 1 : sReverse.order = sForward.order;
3254 1 : sReverse.polycoefvector[0] = adfInvGT[0];
3255 1 : sReverse.polycoefmtx[0] = adfInvGT[1];
3256 1 : sReverse.polycoefmtx[2] = adfInvGT[2];
3257 1 : sReverse.polycoefvector[1] = adfInvGT[3];
3258 1 : sReverse.polycoefmtx[1] = adfInvGT[4];
3259 1 : sReverse.polycoefmtx[3] = adfInvGT[5];
3260 : }
3261 : }
3262 2 : else if( EQUAL(poXForm->GetType(),"GM_PolyPair") )
3263 : {
3264 : bSuccess =
3265 1 : HFAReadAndValidatePoly( poXForm, "forward.", &sForward );
3266 : bSuccess = bSuccess &&
3267 1 : HFAReadAndValidatePoly( poXForm, "reverse.", &sReverse );
3268 : }
3269 :
3270 3 : if( bSuccess )
3271 : {
3272 2 : nStepCount++;
3273 : *ppasPolyListForward = (Efga_Polynomial *)
3274 : CPLRealloc( *ppasPolyListForward,
3275 2 : sizeof(Efga_Polynomial) * nStepCount);
3276 : memcpy( *ppasPolyListForward + nStepCount - 1,
3277 2 : &sForward, sizeof(sForward) );
3278 :
3279 : *ppasPolyListReverse = (Efga_Polynomial *)
3280 : CPLRealloc( *ppasPolyListReverse,
3281 2 : sizeof(Efga_Polynomial) * nStepCount);
3282 : memcpy( *ppasPolyListReverse + nStepCount - 1,
3283 2 : &sReverse, sizeof(sReverse) );
3284 : }
3285 : }
3286 :
3287 2 : return nStepCount;
3288 : }
3289 :
3290 : /************************************************************************/
3291 : /* HFAEvaluateXFormStack() */
3292 : /************************************************************************/
3293 :
3294 36 : int HFAEvaluateXFormStack( int nStepCount, int bForward,
3295 : Efga_Polynomial *pasPolyList,
3296 : double *pdfX, double *pdfY )
3297 :
3298 : {
3299 : int iStep;
3300 :
3301 108 : for( iStep = 0; iStep < nStepCount; iStep++ )
3302 : {
3303 : double dfXOut, dfYOut;
3304 : Efga_Polynomial *psStep;
3305 :
3306 72 : if( bForward )
3307 0 : psStep = pasPolyList + iStep;
3308 : else
3309 72 : psStep = pasPolyList + nStepCount - iStep - 1;
3310 :
3311 72 : if( psStep->order == 1 )
3312 : {
3313 36 : dfXOut = psStep->polycoefvector[0]
3314 36 : + psStep->polycoefmtx[0] * *pdfX
3315 36 : + psStep->polycoefmtx[2] * *pdfY;
3316 :
3317 36 : dfYOut = psStep->polycoefvector[1]
3318 36 : + psStep->polycoefmtx[1] * *pdfX
3319 36 : + psStep->polycoefmtx[3] * *pdfY;
3320 :
3321 36 : *pdfX = dfXOut;
3322 36 : *pdfY = dfYOut;
3323 : }
3324 36 : else if( psStep->order == 2 )
3325 : {
3326 0 : dfXOut = psStep->polycoefvector[0]
3327 0 : + psStep->polycoefmtx[0] * *pdfX
3328 0 : + psStep->polycoefmtx[2] * *pdfY
3329 0 : + psStep->polycoefmtx[4] * *pdfX * *pdfX
3330 0 : + psStep->polycoefmtx[6] * *pdfX * *pdfY
3331 0 : + psStep->polycoefmtx[8] * *pdfY * *pdfY;
3332 0 : dfYOut = psStep->polycoefvector[1]
3333 0 : + psStep->polycoefmtx[1] * *pdfX
3334 0 : + psStep->polycoefmtx[3] * *pdfY
3335 0 : + psStep->polycoefmtx[5] * *pdfX * *pdfX
3336 0 : + psStep->polycoefmtx[7] * *pdfX * *pdfY
3337 0 : + psStep->polycoefmtx[9] * *pdfY * *pdfY;
3338 :
3339 0 : *pdfX = dfXOut;
3340 0 : *pdfY = dfYOut;
3341 : }
3342 36 : else if( psStep->order == 3 )
3343 : {
3344 36 : dfXOut = psStep->polycoefvector[0]
3345 36 : + psStep->polycoefmtx[ 0] * *pdfX
3346 36 : + psStep->polycoefmtx[ 2] * *pdfY
3347 36 : + psStep->polycoefmtx[ 4] * *pdfX * *pdfX
3348 36 : + psStep->polycoefmtx[ 6] * *pdfX * *pdfY
3349 36 : + psStep->polycoefmtx[ 8] * *pdfY * *pdfY
3350 36 : + psStep->polycoefmtx[10] * *pdfX * *pdfX * *pdfX
3351 36 : + psStep->polycoefmtx[12] * *pdfX * *pdfX * *pdfY
3352 36 : + psStep->polycoefmtx[14] * *pdfX * *pdfY * *pdfY
3353 288 : + psStep->polycoefmtx[16] * *pdfY * *pdfY * *pdfY;
3354 36 : dfYOut = psStep->polycoefvector[1]
3355 36 : + psStep->polycoefmtx[ 1] * *pdfX
3356 36 : + psStep->polycoefmtx[ 3] * *pdfY
3357 36 : + psStep->polycoefmtx[ 5] * *pdfX * *pdfX
3358 36 : + psStep->polycoefmtx[ 7] * *pdfX * *pdfY
3359 36 : + psStep->polycoefmtx[ 9] * *pdfY * *pdfY
3360 36 : + psStep->polycoefmtx[11] * *pdfX * *pdfX * *pdfX
3361 36 : + psStep->polycoefmtx[13] * *pdfX * *pdfX * *pdfY
3362 36 : + psStep->polycoefmtx[15] * *pdfX * *pdfY * *pdfY
3363 288 : + psStep->polycoefmtx[17] * *pdfY * *pdfY * *pdfY;
3364 :
3365 36 : *pdfX = dfXOut;
3366 36 : *pdfY = dfYOut;
3367 : }
3368 : else
3369 0 : return FALSE;
3370 : }
3371 :
3372 36 : return TRUE;
3373 : }
3374 :
3375 : /************************************************************************/
3376 : /* HFAWriteXFormStack() */
3377 : /************************************************************************/
3378 :
3379 2 : CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
3380 : Efga_Polynomial **ppasPolyListForward,
3381 : Efga_Polynomial **ppasPolyListReverse )
3382 :
3383 : {
3384 2 : if( nXFormCount == 0 )
3385 0 : return CE_None;
3386 :
3387 2 : if( ppasPolyListForward[0]->order != 1 )
3388 : {
3389 : CPLError( CE_Failure, CPLE_AppDefined,
3390 0 : "For now HFAWriteXFormStack() only supports order 1 polynomials" );
3391 0 : return CE_Failure;
3392 : }
3393 :
3394 2 : if( nBand < 0 || nBand > hHFA->nBands )
3395 0 : return CE_Failure;
3396 :
3397 : /* -------------------------------------------------------------------- */
3398 : /* If no band number is provided, operate on all bands. */
3399 : /* -------------------------------------------------------------------- */
3400 2 : if( nBand == 0 )
3401 : {
3402 1 : CPLErr eErr = CE_None;
3403 :
3404 2 : for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
3405 : {
3406 : eErr = HFAWriteXFormStack( hHFA, nBand, nXFormCount,
3407 : ppasPolyListForward,
3408 1 : ppasPolyListReverse );
3409 1 : if( eErr != CE_None )
3410 0 : return eErr;
3411 : }
3412 :
3413 1 : return eErr;
3414 : }
3415 :
3416 : /* -------------------------------------------------------------------- */
3417 : /* Fetch our band node. */
3418 : /* -------------------------------------------------------------------- */
3419 1 : HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
3420 : HFAEntry *poXFormHeader;
3421 :
3422 1 : poXFormHeader = poBandNode->GetNamedChild( "MapToPixelXForm" );
3423 1 : if( poXFormHeader == NULL )
3424 : {
3425 : poXFormHeader = new HFAEntry( hHFA, "MapToPixelXForm",
3426 1 : "Exfr_GenericXFormHeader", poBandNode );
3427 1 : poXFormHeader->MakeData( 23 );
3428 1 : poXFormHeader->SetPosition();
3429 1 : poXFormHeader->SetStringField( "titleList.string", "Affine" );
3430 : }
3431 :
3432 : /* -------------------------------------------------------------------- */
3433 : /* Loop over XForms. */
3434 : /* -------------------------------------------------------------------- */
3435 2 : for( int iXForm = 0; iXForm < nXFormCount; iXForm++ )
3436 : {
3437 1 : Efga_Polynomial *psForward = *ppasPolyListForward + iXForm;
3438 1 : CPLString osXFormName;
3439 1 : osXFormName.Printf( "XForm%d", iXForm );
3440 :
3441 1 : HFAEntry *poXForm = poXFormHeader->GetNamedChild( osXFormName );
3442 :
3443 1 : if( poXForm == NULL )
3444 : {
3445 : poXForm = new HFAEntry( hHFA, osXFormName, "Efga_Polynomial",
3446 1 : poXFormHeader );
3447 1 : poXForm->MakeData( 136 );
3448 1 : poXForm->SetPosition();
3449 : }
3450 :
3451 1 : poXForm->SetIntField( "order", 1 );
3452 1 : poXForm->SetIntField( "numdimtransform", 2 );
3453 1 : poXForm->SetIntField( "numdimpolynomial", 2 );
3454 1 : poXForm->SetIntField( "termcount", 3 );
3455 1 : poXForm->SetIntField( "exponentlist[0]", 0 );
3456 1 : poXForm->SetIntField( "exponentlist[1]", 0 );
3457 1 : poXForm->SetIntField( "exponentlist[2]", 1 );
3458 1 : poXForm->SetIntField( "exponentlist[3]", 0 );
3459 1 : poXForm->SetIntField( "exponentlist[4]", 0 );
3460 1 : poXForm->SetIntField( "exponentlist[5]", 1 );
3461 :
3462 1 : poXForm->SetIntField( "polycoefmtx[-3]", EPT_f64 );
3463 1 : poXForm->SetIntField( "polycoefmtx[-2]", 2 );
3464 1 : poXForm->SetIntField( "polycoefmtx[-1]", 2 );
3465 : poXForm->SetDoubleField( "polycoefmtx[0]",
3466 1 : psForward->polycoefmtx[0] );
3467 : poXForm->SetDoubleField( "polycoefmtx[1]",
3468 1 : psForward->polycoefmtx[1] );
3469 : poXForm->SetDoubleField( "polycoefmtx[2]",
3470 1 : psForward->polycoefmtx[2] );
3471 : poXForm->SetDoubleField( "polycoefmtx[3]",
3472 1 : psForward->polycoefmtx[3] );
3473 :
3474 1 : poXForm->SetIntField( "polycoefvector[-3]", EPT_f64 );
3475 1 : poXForm->SetIntField( "polycoefvector[-2]", 1 );
3476 1 : poXForm->SetIntField( "polycoefvector[-1]", 2 );
3477 : poXForm->SetDoubleField( "polycoefvector[0]",
3478 1 : psForward->polycoefvector[0] );
3479 : poXForm->SetDoubleField( "polycoefvector[1]",
3480 1 : psForward->polycoefvector[1] );
3481 : }
3482 :
3483 1 : return CE_None;
3484 : }
3485 :
3486 : /************************************************************************/
3487 : /* HFAReadCameraModel() */
3488 : /************************************************************************/
3489 :
3490 376 : char **HFAReadCameraModel( HFAHandle hHFA )
3491 :
3492 : {
3493 376 : if( hHFA->nBands == 0 )
3494 0 : return NULL;
3495 :
3496 : /* -------------------------------------------------------------------- */
3497 : /* Get the camera model node, and confirm it's type. */
3498 : /* -------------------------------------------------------------------- */
3499 : HFAEntry *poXForm;
3500 :
3501 : poXForm =
3502 376 : hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
3503 376 : if( poXForm == NULL )
3504 370 : return NULL;
3505 :
3506 6 : if( !EQUAL(poXForm->GetType(),"Camera_ModelX") )
3507 5 : return NULL;
3508 :
3509 : /* -------------------------------------------------------------------- */
3510 : /* Convert the values to metadata. */
3511 : /* -------------------------------------------------------------------- */
3512 : const char *pszValue;
3513 : int i;
3514 1 : char **papszMD = NULL;
3515 : static const char *apszFields[] = {
3516 : "direction", "refType", "demsource", "PhotoDirection", "RotationSystem",
3517 : "demfilename", "demzunits",
3518 : "forSrcAffine[0]", "forSrcAffine[1]", "forSrcAffine[2]",
3519 : "forSrcAffine[3]", "forSrcAffine[4]", "forSrcAffine[5]",
3520 : "forDstAffine[0]", "forDstAffine[1]", "forDstAffine[2]",
3521 : "forDstAffine[3]", "forDstAffine[4]", "forDstAffine[5]",
3522 : "invSrcAffine[0]", "invSrcAffine[1]", "invSrcAffine[2]",
3523 : "invSrcAffine[3]", "invSrcAffine[4]", "invSrcAffine[5]",
3524 : "invDstAffine[0]", "invDstAffine[1]", "invDstAffine[2]",
3525 : "invDstAffine[3]", "invDstAffine[4]", "invDstAffine[5]",
3526 : "z_mean", "lat0", "lon0",
3527 : "coeffs[0]", "coeffs[1]", "coeffs[2]",
3528 : "coeffs[3]", "coeffs[4]", "coeffs[5]",
3529 : "coeffs[6]", "coeffs[7]", "coeffs[8]",
3530 : "LensDistortion[0]", "LensDistortion[1]", "LensDistortion[2]",
3531 : NULL };
3532 :
3533 47 : for( i = 0; apszFields[i] != NULL; i++ )
3534 : {
3535 46 : pszValue = poXForm->GetStringField( apszFields[i] );
3536 46 : if( pszValue == NULL )
3537 1 : pszValue = "";
3538 :
3539 46 : papszMD = CSLSetNameValue( papszMD, apszFields[i], pszValue );
3540 : }
3541 :
3542 : /* -------------------------------------------------------------------- */
3543 : /* Create a pseudo-entry for the MIFObject with the */
3544 : /* outputProjection. */
3545 : /* -------------------------------------------------------------------- */
3546 1 : HFAEntry *poProjInfo = HFAEntry::BuildEntryFromMIFObject( poXForm, "outputProjection" );
3547 1 : if (poProjInfo)
3548 : {
3549 : /* -------------------------------------------------------------------- */
3550 : /* Fetch the datum. */
3551 : /* -------------------------------------------------------------------- */
3552 : Eprj_Datum sDatum;
3553 :
3554 1 : memset( &sDatum, 0, sizeof(sDatum));
3555 :
3556 : sDatum.datumname =
3557 1 : (char *) poProjInfo->GetStringField("earthModel.datum.datumname");
3558 : sDatum.type = (Eprj_DatumType) poProjInfo->GetIntField(
3559 1 : "earthModel.datum.type");
3560 :
3561 8 : for( i = 0; i < 7; i++ )
3562 : {
3563 : char szFieldName[60];
3564 :
3565 7 : sprintf( szFieldName, "earthModel.datum.params[%d]", i );
3566 7 : sDatum.params[i] = poProjInfo->GetDoubleField(szFieldName);
3567 : }
3568 :
3569 : sDatum.gridname = (char *)
3570 1 : poProjInfo->GetStringField("earthModel.datum.gridname");
3571 :
3572 : /* -------------------------------------------------------------------- */
3573 : /* Fetch the projection parameters. */
3574 : /* -------------------------------------------------------------------- */
3575 : Eprj_ProParameters sPro;
3576 :
3577 1 : memset( &sPro, 0, sizeof(sPro) );
3578 :
3579 1 : sPro.proType = (Eprj_ProType) poProjInfo->GetIntField("projectionObject.proType");
3580 1 : sPro.proNumber = poProjInfo->GetIntField("projectionObject.proNumber");
3581 1 : sPro.proExeName = (char *) poProjInfo->GetStringField("projectionObject.proExeName");
3582 1 : sPro.proName = (char *) poProjInfo->GetStringField("projectionObject.proName");
3583 1 : sPro.proZone = poProjInfo->GetIntField("projectionObject.proZone");
3584 :
3585 16 : for( i = 0; i < 15; i++ )
3586 : {
3587 : char szFieldName[40];
3588 :
3589 15 : sprintf( szFieldName, "projectionObject.proParams[%d]", i );
3590 15 : sPro.proParams[i] = poProjInfo->GetDoubleField(szFieldName);
3591 : }
3592 :
3593 : /* -------------------------------------------------------------------- */
3594 : /* Fetch the spheroid. */
3595 : /* -------------------------------------------------------------------- */
3596 : sPro.proSpheroid.sphereName = (char *)
3597 1 : poProjInfo->GetStringField("earthModel.proSpheroid.sphereName");
3598 1 : sPro.proSpheroid.a = poProjInfo->GetDoubleField("earthModel.proSpheroid.a");
3599 1 : sPro.proSpheroid.b = poProjInfo->GetDoubleField("earthModel.proSpheroid.b");
3600 : sPro.proSpheroid.eSquared =
3601 1 : poProjInfo->GetDoubleField("earthModel.proSpheroid.eSquared");
3602 : sPro.proSpheroid.radius =
3603 1 : poProjInfo->GetDoubleField("earthModel.proSpheroid.radius");
3604 :
3605 : /* -------------------------------------------------------------------- */
3606 : /* Fetch the projection info. */
3607 : /* -------------------------------------------------------------------- */
3608 : char *pszProjection;
3609 :
3610 : // poProjInfo->DumpFieldValues( stdout, "" );
3611 :
3612 1 : pszProjection = HFAPCSStructToWKT( &sDatum, &sPro, NULL, NULL );
3613 :
3614 1 : if( pszProjection )
3615 : {
3616 : papszMD =
3617 1 : CSLSetNameValue( papszMD, "outputProjection", pszProjection );
3618 1 : CPLFree( pszProjection );
3619 : }
3620 :
3621 1 : delete poProjInfo;
3622 : }
3623 :
3624 : /* -------------------------------------------------------------------- */
3625 : /* Fetch the horizontal units. */
3626 : /* -------------------------------------------------------------------- */
3627 1 : pszValue = poXForm->GetStringField( "outputHorizontalUnits.string" );
3628 1 : if( pszValue == NULL )
3629 0 : pszValue = "";
3630 :
3631 1 : papszMD = CSLSetNameValue( papszMD, "outputHorizontalUnits", pszValue );
3632 :
3633 : /* -------------------------------------------------------------------- */
3634 : /* Fetch the elevationinfo. */
3635 : /* -------------------------------------------------------------------- */
3636 1 : HFAEntry *poElevInfo = HFAEntry::BuildEntryFromMIFObject( poXForm, "outputElevationInfo" );
3637 1 : if ( poElevInfo )
3638 : {
3639 : //poElevInfo->DumpFieldValues( stdout, "" );
3640 :
3641 1 : if( poElevInfo->GetDataSize() != 0 )
3642 : {
3643 : static const char *apszEFields[] = {
3644 : "verticalDatum.datumname",
3645 : "verticalDatum.type",
3646 : "elevationUnit",
3647 : "elevationType",
3648 : NULL };
3649 :
3650 5 : for( i = 0; apszEFields[i] != NULL; i++ )
3651 : {
3652 4 : pszValue = poElevInfo->GetStringField( apszEFields[i] );
3653 4 : if( pszValue == NULL )
3654 0 : pszValue = "";
3655 :
3656 4 : papszMD = CSLSetNameValue( papszMD, apszEFields[i], pszValue );
3657 : }
3658 : }
3659 :
3660 1 : delete poElevInfo;
3661 : }
3662 :
3663 1 : return papszMD;
3664 : }
3665 :
3666 : /************************************************************************/
3667 : /* HFASetGeoTransform() */
3668 : /* */
3669 : /* Set a MapInformation and XForm block. Allows for rotated */
3670 : /* and shared geotransforms. */
3671 : /************************************************************************/
3672 :
3673 1 : CPLErr HFASetGeoTransform( HFAHandle hHFA,
3674 : const char *pszProName,
3675 : const char *pszUnits,
3676 : double *padfGeoTransform )
3677 :
3678 : {
3679 : /* -------------------------------------------------------------------- */
3680 : /* Write MapInformation. */
3681 : /* -------------------------------------------------------------------- */
3682 : int nBand;
3683 :
3684 2 : for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
3685 : {
3686 1 : HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
3687 :
3688 1 : HFAEntry *poMI = poBandNode->GetNamedChild( "MapInformation" );
3689 1 : if( poMI == NULL )
3690 : {
3691 : poMI = new HFAEntry( hHFA, "MapInformation",
3692 1 : "Eimg_MapInformation", poBandNode );
3693 1 : poMI->MakeData( 18 + strlen(pszProName) + strlen(pszUnits) );
3694 1 : poMI->SetPosition();
3695 : }
3696 :
3697 1 : poMI->SetStringField( "projection.string", pszProName );
3698 1 : poMI->SetStringField( "units.string", pszUnits );
3699 : }
3700 :
3701 : /* -------------------------------------------------------------------- */
3702 : /* Write XForm. */
3703 : /* -------------------------------------------------------------------- */
3704 : Efga_Polynomial sForward, sReverse;
3705 : double adfAdjTransform[6], adfRevTransform[6];
3706 :
3707 : // Offset by half pixel.
3708 :
3709 1 : memcpy( adfAdjTransform, padfGeoTransform, sizeof(double) * 6 );
3710 1 : adfAdjTransform[0] += adfAdjTransform[1] * 0.5;
3711 1 : adfAdjTransform[0] += adfAdjTransform[2] * 0.5;
3712 1 : adfAdjTransform[3] += adfAdjTransform[4] * 0.5;
3713 1 : adfAdjTransform[3] += adfAdjTransform[5] * 0.5;
3714 :
3715 : // Invert
3716 1 : HFAInvGeoTransform( adfAdjTransform, adfRevTransform );
3717 :
3718 : // Assign to polynomial object.
3719 :
3720 1 : sForward.order = 1;
3721 1 : sForward.polycoefvector[0] = adfRevTransform[0];
3722 1 : sForward.polycoefmtx[0] = adfRevTransform[1];
3723 1 : sForward.polycoefmtx[1] = adfRevTransform[4];
3724 1 : sForward.polycoefvector[1] = adfRevTransform[3];
3725 1 : sForward.polycoefmtx[2] = adfRevTransform[2];
3726 1 : sForward.polycoefmtx[3] = adfRevTransform[5];
3727 :
3728 1 : sReverse = sForward;
3729 1 : Efga_Polynomial *psForward=&sForward, *psReverse=&sReverse;
3730 :
3731 1 : return HFAWriteXFormStack( hHFA, 0, 1, &psForward, &psReverse );
3732 : }
3733 :
3734 : /************************************************************************/
3735 : /* HFARenameReferences() */
3736 : /* */
3737 : /* Rename references in this .img file from the old basename to */
3738 : /* a new basename. This should be passed on to .aux and .rrd */
3739 : /* files and should include references to .aux, .rrd and .ige. */
3740 : /************************************************************************/
3741 :
3742 4 : CPLErr HFARenameReferences( HFAHandle hHFA,
3743 : const char *pszNewBase,
3744 : const char *pszOldBase )
3745 :
3746 : {
3747 : /* -------------------------------------------------------------------- */
3748 : /* Handle RRDNamesList updates. */
3749 : /* -------------------------------------------------------------------- */
3750 : size_t iNode;
3751 : std::vector<HFAEntry*> apoNodeList =
3752 4 : hHFA->poRoot->FindChildren( "RRDNamesList", NULL );
3753 :
3754 6 : for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
3755 : {
3756 2 : HFAEntry *poRRDNL = apoNodeList[iNode];
3757 2 : std::vector<CPLString> aosNL;
3758 :
3759 : // Collect all the existing names.
3760 2 : int i, nNameCount = poRRDNL->GetFieldCount( "nameList" );
3761 :
3762 2 : CPLString osAlgorithm = poRRDNL->GetStringField("algorithm.string");
3763 4 : for( i = 0; i < nNameCount; i++ )
3764 : {
3765 2 : CPLString osFN;
3766 2 : osFN.Printf( "nameList[%d].string", i );
3767 2 : aosNL.push_back( poRRDNL->GetStringField(osFN) );
3768 : }
3769 :
3770 : // Adjust the names to the new form.
3771 4 : for( i = 0; i < nNameCount; i++ )
3772 : {
3773 2 : if( strncmp(aosNL[i],pszOldBase,strlen(pszOldBase)) == 0 )
3774 : {
3775 2 : CPLString osNew = pszNewBase;
3776 2 : osNew += aosNL[i].c_str() + strlen(pszOldBase);
3777 2 : aosNL[i] = osNew;
3778 : }
3779 : }
3780 :
3781 : // try to make sure the RRDNamesList is big enough to hold the
3782 : // adjusted name list.
3783 2 : if( strlen(pszNewBase) > strlen(pszOldBase) )
3784 : {
3785 1 : CPLDebug( "HFA", "Growing RRDNamesList to hold new names" );
3786 : poRRDNL->MakeData( poRRDNL->GetDataSize()
3787 1 : + nNameCount * (strlen(pszNewBase) - strlen(pszOldBase)) );
3788 : }
3789 :
3790 : // Initialize the whole thing to zeros for a clean start.
3791 2 : memset( poRRDNL->GetData(), 0, poRRDNL->GetDataSize() );
3792 :
3793 : // Write the updates back to the file.
3794 2 : poRRDNL->SetStringField( "algorithm.string", osAlgorithm );
3795 4 : for( i = 0; i < nNameCount; i++ )
3796 : {
3797 2 : CPLString osFN;
3798 2 : osFN.Printf( "nameList[%d].string", i );
3799 2 : poRRDNL->SetStringField( osFN, aosNL[i] );
3800 : }
3801 : }
3802 :
3803 : /* -------------------------------------------------------------------- */
3804 : /* spill file references. */
3805 : /* -------------------------------------------------------------------- */
3806 : apoNodeList =
3807 4 : hHFA->poRoot->FindChildren( "ExternalRasterDMS", "ImgExternalRaster" );
3808 :
3809 8 : for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
3810 : {
3811 4 : HFAEntry *poERDMS = apoNodeList[iNode];
3812 :
3813 4 : if( poERDMS == NULL )
3814 0 : continue;
3815 :
3816 : // Fetch all existing values.
3817 4 : CPLString osFileName = poERDMS->GetStringField("fileName.string");
3818 : GInt32 anValidFlagsOffset[2], anStackDataOffset[2];
3819 : GInt32 nStackCount, nStackIndex;
3820 :
3821 : anValidFlagsOffset[0] =
3822 4 : poERDMS->GetIntField( "layerStackValidFlagsOffset[0]" );
3823 : anValidFlagsOffset[1] =
3824 4 : poERDMS->GetIntField( "layerStackValidFlagsOffset[1]" );
3825 :
3826 : anStackDataOffset[0] =
3827 4 : poERDMS->GetIntField( "layerStackDataOffset[0]" );
3828 : anStackDataOffset[1] =
3829 4 : poERDMS->GetIntField( "layerStackDataOffset[1]" );
3830 :
3831 4 : nStackCount = poERDMS->GetIntField( "layerStackCount" );
3832 4 : nStackIndex = poERDMS->GetIntField( "layerStackIndex" );
3833 :
3834 : // Update the filename.
3835 4 : if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
3836 : {
3837 4 : CPLString osNew = pszNewBase;
3838 4 : osNew += osFileName.c_str() + strlen(pszOldBase);
3839 4 : osFileName = osNew;
3840 : }
3841 :
3842 : // Grow the node if needed.
3843 4 : if( strlen(pszNewBase) > strlen(pszOldBase) )
3844 : {
3845 2 : CPLDebug( "HFA", "Growing ExternalRasterDMS to hold new names" );
3846 : poERDMS->MakeData( poERDMS->GetDataSize()
3847 2 : + (strlen(pszNewBase) - strlen(pszOldBase)) );
3848 : }
3849 :
3850 : // Initialize the whole thing to zeros for a clean start.
3851 4 : memset( poERDMS->GetData(), 0, poERDMS->GetDataSize() );
3852 :
3853 : // Write it all out again, this may change the size of the node.
3854 4 : poERDMS->SetStringField( "fileName.string", osFileName );
3855 : poERDMS->SetIntField( "layerStackValidFlagsOffset[0]",
3856 4 : anValidFlagsOffset[0] );
3857 : poERDMS->SetIntField( "layerStackValidFlagsOffset[1]",
3858 4 : anValidFlagsOffset[1] );
3859 :
3860 : poERDMS->SetIntField( "layerStackDataOffset[0]",
3861 4 : anStackDataOffset[0] );
3862 : poERDMS->SetIntField( "layerStackDataOffset[1]",
3863 4 : anStackDataOffset[1] );
3864 :
3865 4 : poERDMS->SetIntField( "layerStackCount", nStackCount );
3866 4 : poERDMS->SetIntField( "layerStackIndex", nStackIndex );
3867 : }
3868 :
3869 : /* -------------------------------------------------------------------- */
3870 : /* DependentFile */
3871 : /* -------------------------------------------------------------------- */
3872 : apoNodeList =
3873 4 : hHFA->poRoot->FindChildren( "DependentFile", "Eimg_DependentFile" );
3874 :
3875 6 : for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
3876 : {
3877 : CPLString osFileName = apoNodeList[iNode]->
3878 2 : GetStringField("dependent.string");
3879 :
3880 : // Grow the node if needed.
3881 2 : if( strlen(pszNewBase) > strlen(pszOldBase) )
3882 : {
3883 1 : CPLDebug( "HFA", "Growing DependentFile to hold new names" );
3884 : apoNodeList[iNode]->MakeData( apoNodeList[iNode]->GetDataSize()
3885 : + (strlen(pszNewBase)
3886 1 : - strlen(pszOldBase)) );
3887 : }
3888 :
3889 : // Update the filename.
3890 2 : if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
3891 : {
3892 2 : CPLString osNew = pszNewBase;
3893 2 : osNew += osFileName.c_str() + strlen(pszOldBase);
3894 2 : osFileName = osNew;
3895 : }
3896 :
3897 2 : apoNodeList[iNode]->SetStringField( "dependent.string", osFileName );
3898 : }
3899 :
3900 4 : return CE_None;
3901 : }
|