Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: Erdas Imagine (.img) Translator
5 : * Purpose: Private class declarations for the HFA classes used to read
6 : * Erdas Imagine (.img) files. Public (C callable) declarations
7 : * are in hfa.h.
8 : * Author: Frank Warmerdam, warmerdam@pobox.com
9 : *
10 : ******************************************************************************
11 : * Copyright (c) 1999, Intergraph Corporation
12 : *
13 : * SPDX-License-Identifier: MIT
14 : ****************************************************************************/
15 :
16 : #ifndef HFA_P_H_INCLUDED
17 : #define HFA_P_H_INCLUDED
18 :
19 : #include "cpl_port.h"
20 : #include "hfa.h"
21 :
22 : #include <cstdio>
23 : #include <memory>
24 : #include <vector>
25 : #include <set>
26 :
27 : #include "cpl_error.h"
28 : #include "cpl_vsi.h"
29 : #include "ogr_spatialref.h"
30 :
31 : #ifdef CPL_LSB
32 : #define HFAStandard(n, p) \
33 : { \
34 : }
35 : #else
36 : void HFAStandard(int, void *);
37 : #endif
38 :
39 : #include "hfa.h"
40 :
41 : class HFABand;
42 : class HFADictionary;
43 : class HFAEntry;
44 : class HFASpillFile;
45 : class HFAType;
46 :
47 : /************************************************************************/
48 : /* Flag indicating read/write, or read-only access to data. */
49 : /************************************************************************/
50 : typedef enum
51 : {
52 : /*! Read only (no update) access */ HFA_ReadOnly = 0,
53 : /*! Read/write access. */ HFA_Update = 1
54 : } HFAAccess;
55 :
56 : /************************************************************************/
57 : /* HFAInfo_t */
58 : /* */
59 : /* This is just a structure, and used hold info about the whole */
60 : /* dataset within hfaopen.cpp */
61 : /************************************************************************/
62 : struct hfainfo
63 : {
64 : VSILFILE *fp;
65 :
66 : char *pszPath;
67 : char *pszFilename; // Sans path.
68 : char *pszIGEFilename; // Sans path.
69 :
70 : HFAAccess eAccess;
71 :
72 : GUInt32 nEndOfFile;
73 : GUInt32 nRootPos;
74 : GUInt32 nDictionaryPos;
75 :
76 : GInt16 nEntryHeaderLength;
77 : GInt32 nVersion;
78 :
79 : bool bTreeDirty;
80 : HFAEntry *poRoot;
81 :
82 : HFADictionary *poDictionary;
83 : char *pszDictionary;
84 :
85 : int nXSize;
86 : int nYSize;
87 :
88 : int nBands;
89 : HFABand **papoBand;
90 :
91 : void *pMapInfo;
92 : void *pDatum;
93 : void *pProParameters;
94 :
95 : struct hfainfo *psDependent;
96 : };
97 :
98 : typedef struct hfainfo HFAInfo_t;
99 :
100 : GUInt32 HFAAllocateSpace(HFAInfo_t *, GUInt32);
101 : CPLErr HFAParseBandInfo(HFAInfo_t *);
102 : HFAInfo_t *HFAGetDependent(HFAInfo_t *, const char *);
103 : HFAInfo_t *HFACreateDependent(HFAInfo_t *psBase);
104 : bool HFACreateSpillStack(HFAInfo_t *, int nXSize, int nYSize, int nLayers,
105 : int nBlockSize, EPTType eDataType,
106 : GIntBig *pnValidFlagsOffset, GIntBig *pnDataOffset);
107 :
108 : const char *const *GetHFAAuxMetaDataList();
109 :
110 : double *HFAReadBFUniqueBins(HFAEntry *poBinFunc, int nPCTColors);
111 :
112 : int CPL_DLL HFACreateLayer(HFAHandle psInfo, HFAEntry *poParent,
113 : const char *pszLayerName, int bOverview,
114 : int nBlockSize, int bCreateCompressed,
115 : int bCreateLargeRaster, int bDependentLayer,
116 : int nXSize, int nYSize, EPTType eDataType,
117 : char **papszOptions,
118 :
119 : // These are only related to external (large) files.
120 : GIntBig nStackValidFlagsOffset,
121 : GIntBig nStackDataOffset, int nStackCount,
122 : int nStackIndex);
123 :
124 : std::unique_ptr<OGRSpatialReference>
125 : HFAPCSStructToOSR(const Eprj_Datum *psDatum, const Eprj_ProParameters *psPro,
126 : const Eprj_MapInfo *psMapInfo, HFAEntry *poMapInformation);
127 :
128 : const char *const *HFAGetDatumMap();
129 : const char *const *HFAGetUnitMap();
130 :
131 : /************************************************************************/
132 : /* HFABand */
133 : /************************************************************************/
134 :
135 : class HFABand
136 : {
137 : int nBlocks;
138 :
139 : // Used for single-file modification.
140 : vsi_l_offset *panBlockStart;
141 : int *panBlockSize;
142 : int *panBlockFlag;
143 :
144 : // Used for spill-file modification.
145 : vsi_l_offset nBlockStart;
146 : vsi_l_offset nBlockSize;
147 : int nLayerStackCount;
148 : int nLayerStackIndex;
149 :
150 : #define BFLG_VALID 0x01
151 : #define BFLG_COMPRESSED 0x02
152 :
153 : int nPCTColors;
154 : double *apadfPCT[4];
155 : double *padfPCTBins;
156 :
157 : CPLErr LoadBlockInfo();
158 : CPLErr LoadExternalBlockInfo();
159 :
160 : void ReAllocBlock(int iBlock, int nSize);
161 : void NullBlock(void *);
162 :
163 : CPLString osOverName;
164 :
165 : public:
166 : HFABand(HFAInfo_t *, HFAEntry *);
167 : ~HFABand();
168 :
169 : HFAInfo_t *psInfo;
170 :
171 : VSILFILE *fpExternal;
172 :
173 : EPTType eDataType;
174 : HFAEntry *poNode;
175 :
176 : int nBlockXSize;
177 : int nBlockYSize;
178 :
179 : int nWidth;
180 : int nHeight;
181 :
182 : int nBlocksPerRow;
183 : int nBlocksPerColumn;
184 :
185 : bool bNoDataSet;
186 : double dfNoData;
187 :
188 : bool bOverviewsPending;
189 : int nOverviews;
190 : HFABand **papoOverviews;
191 :
192 : CPLErr GetRasterBlock(int nXBlock, int nYBlock, void *pData, int nDataSize);
193 : CPLErr SetRasterBlock(int nXBlock, int nYBlock, void *pData);
194 :
195 : const char *GetBandName();
196 : void SetBandName(const char *pszName);
197 :
198 : CPLErr SetNoDataValue(double dfValue);
199 :
200 : CPLErr GetPCT(int *, double **, double **, double **, double **, double **);
201 : CPLErr SetPCT(int, const double *, const double *, const double *,
202 : const double *);
203 :
204 : int CreateOverview(int nOverviewLevel, const char *pszResampling);
205 : CPLErr CleanOverviews();
206 :
207 : CPLErr LoadOverviews();
208 : };
209 :
210 : /************************************************************************/
211 : /* HFAEntry */
212 : /* */
213 : /* Base class for all entry types. Most entry types do not */
214 : /* have a subclass, and are just handled generically with this */
215 : /* class. */
216 : /************************************************************************/
217 : class HFAEntry
218 : {
219 : bool bDirty;
220 : GUInt32 nFilePos;
221 :
222 : HFAInfo_t *psHFA;
223 : HFAEntry *poParent;
224 : HFAEntry *poPrev;
225 :
226 : GUInt32 nNextPos;
227 : HFAEntry *poNext;
228 :
229 : GUInt32 nChildPos;
230 : HFAEntry *poChild;
231 :
232 : char szName[64];
233 : char szType[32];
234 :
235 : HFAType *poType;
236 :
237 : GUInt32 nDataPos;
238 : GUInt32 nDataSize;
239 : GByte *pabyData;
240 :
241 : void LoadData();
242 :
243 : bool GetFieldValue(const char *, char, void *, int *pnRemainingDataSize);
244 : CPLErr SetFieldValue(const char *, char, void *);
245 :
246 : bool bIsMIFObject;
247 :
248 : HFAEntry();
249 : HFAEntry(const char *pszDictionary, const char *pszTypeName,
250 : int nDataSizeIn, GByte *pabyDataIn);
251 : std::vector<HFAEntry *> FindChildren(const char *pszName,
252 : const char *pszType, int nRecLevel,
253 : int *pbErrorDetected);
254 :
255 : public:
256 : static HFAEntry *New(HFAInfo_t *psHFA, GUInt32 nPos, HFAEntry *poParent,
257 : HFAEntry *poPrev) CPL_WARN_UNUSED_RESULT;
258 :
259 : HFAEntry(HFAInfo_t *psHFA, const char *pszNodeName, const char *pszTypeName,
260 : HFAEntry *poParent);
261 :
262 : static HFAEntry *New(HFAInfo_t *psHFA, const char *pszNodeName,
263 : const char *pszTypeName,
264 : HFAEntry *poParent) CPL_WARN_UNUSED_RESULT;
265 :
266 : virtual ~HFAEntry();
267 :
268 : static HFAEntry *BuildEntryFromMIFObject(HFAEntry *poContainer,
269 : const char *pszMIFObjectPath)
270 : CPL_WARN_UNUSED_RESULT;
271 :
272 : CPLErr RemoveAndDestroy();
273 :
274 552 : GUInt32 GetFilePos() const CPL_WARN_UNUSED_RESULT
275 : {
276 552 : return nFilePos;
277 : }
278 :
279 68984 : const char *GetName() const CPL_WARN_UNUSED_RESULT
280 : {
281 68984 : return szName;
282 : }
283 :
284 : void SetName(const char *pszNodeName);
285 :
286 5676 : const char *GetType() const CPL_WARN_UNUSED_RESULT
287 : {
288 5676 : return szType;
289 : }
290 :
291 : HFAType *GetTypeObject() CPL_WARN_UNUSED_RESULT;
292 :
293 512 : GByte *GetData() CPL_WARN_UNUSED_RESULT
294 : {
295 512 : LoadData();
296 512 : return pabyData;
297 : }
298 :
299 385 : GUInt32 GetDataPos() const CPL_WARN_UNUSED_RESULT
300 : {
301 385 : return nDataPos;
302 : }
303 :
304 518 : GUInt32 GetDataSize() const CPL_WARN_UNUSED_RESULT
305 : {
306 518 : return nDataSize;
307 : }
308 :
309 : HFAEntry *GetChild() CPL_WARN_UNUSED_RESULT;
310 : HFAEntry *GetNext() CPL_WARN_UNUSED_RESULT;
311 : HFAEntry *GetNamedChild(const char *) CPL_WARN_UNUSED_RESULT;
312 : std::vector<HFAEntry *>
313 : FindChildren(const char *pszName,
314 : const char *pszType) CPL_WARN_UNUSED_RESULT;
315 :
316 : GInt32 GetIntField(const char *, CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
317 : double GetDoubleField(const char *,
318 : CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
319 : const char *
320 : GetStringField(const char *, CPLErr * = nullptr,
321 : int *pnRemainingDataSize = nullptr) CPL_WARN_UNUSED_RESULT;
322 : GIntBig GetBigIntField(const char *,
323 : CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
324 : int GetFieldCount(const char *, CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
325 :
326 : CPLErr SetIntField(const char *, int);
327 : CPLErr SetDoubleField(const char *, double);
328 : CPLErr SetStringField(const char *, const char *);
329 :
330 : void DumpFieldValues(FILE *, const char * = nullptr);
331 :
332 : void SetPosition();
333 : CPLErr FlushToDisk();
334 :
335 : void MarkDirty();
336 : GByte *MakeData(int nSize = 0);
337 : };
338 :
339 : /************************************************************************/
340 : /* HFAField */
341 : /* */
342 : /* A field in a HFAType in the dictionary. */
343 : /************************************************************************/
344 :
345 : class HFAField
346 : {
347 : public:
348 : int nBytes;
349 :
350 : int nItemCount;
351 : // TODO(schwehr): Rename chPointer to something more meaningful.
352 : // It's not a pointer.
353 : char chPointer; // '\0', '*' or 'p'
354 : char chItemType; // 1|2|4|e|...
355 :
356 : char *pszItemObjectType; // if chItemType == 'o'
357 : HFAType *poItemObjectType;
358 :
359 : char **papszEnumNames; // Normally NULL if not an enum.
360 :
361 : char *pszFieldName;
362 :
363 : char szNumberString[36]; // Buffer used to return int as a string.
364 :
365 : HFAField();
366 : ~HFAField();
367 :
368 : const char *Initialize(const char *);
369 :
370 : bool CompleteDefn(HFADictionary *);
371 :
372 : void Dump(FILE *);
373 :
374 : bool ExtractInstValue(const char *pszField, int nIndexValue,
375 : GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
376 : char chReqType, void *pReqReturn,
377 : int *pnRemainingDataSize = nullptr);
378 :
379 : CPLErr SetInstValue(const char *pszField, int nIndexValue, GByte *pabyData,
380 : GUInt32 nDataOffset, int nDataSize, char chReqType,
381 : void *pValue);
382 :
383 : void DumpInstValue(FILE *fpOut, GByte *pabyData, GUInt32 nDataOffset,
384 : int nDataSize, const char *pszPrefix = nullptr);
385 :
386 : int GetInstBytes(GByte *, int, std::set<HFAField *> &oVisitedFields);
387 : int GetInstCount(GByte *pabyData, int nDataSize) const;
388 : };
389 :
390 : /************************************************************************/
391 : /* HFAType */
392 : /* */
393 : /* A type in the dictionary. */
394 : /************************************************************************/
395 :
396 : class HFAType
397 : {
398 : bool bInCompleteDefn;
399 :
400 : public:
401 : int nBytes;
402 :
403 : std::vector<std::unique_ptr<HFAField>> apoFields;
404 :
405 : char *pszTypeName;
406 :
407 : HFAType();
408 : ~HFAType();
409 :
410 : const char *Initialize(const char *);
411 :
412 : bool CompleteDefn(HFADictionary *);
413 :
414 : void Dump(FILE *);
415 :
416 : int GetInstBytes(GByte *, int, std::set<HFAField *> &oVisitedFields) const;
417 : int GetInstCount(const char *pszField, GByte *pabyData, GUInt32 nDataOffset,
418 : int nDataSize);
419 : bool ExtractInstValue(const char *pszField, GByte *pabyData,
420 : GUInt32 nDataOffset, int nDataSize, char chReqType,
421 : void *pReqReturn, int *pnRemainingDataSize);
422 : CPLErr SetInstValue(const char *pszField, GByte *pabyData,
423 : GUInt32 nDataOffset, int nDataSize, char chReqType,
424 : void *pValue);
425 : void DumpInstValue(FILE *fpOut, GByte *pabyData, GUInt32 nDataOffset,
426 : int nDataSize, const char *pszPrefix = nullptr) const;
427 : };
428 :
429 : /************************************************************************/
430 : /* HFADictionary */
431 : /************************************************************************/
432 :
433 : class HFADictionary
434 : {
435 : public:
436 : explicit HFADictionary(const char *pszDict);
437 : ~HFADictionary();
438 :
439 : HFAType *FindType(const char *);
440 : void AddType(HFAType *);
441 :
442 : static int GetItemSize(char);
443 :
444 : void Dump(FILE *);
445 :
446 : private:
447 : int nTypes;
448 : int nTypesMax;
449 : HFAType **papoTypes;
450 :
451 : public:
452 : // TODO(schwehr): Make these members private.
453 : CPLString osDictionaryText;
454 : bool bDictionaryTextDirty;
455 : };
456 :
457 : /************************************************************************/
458 : /* HFACompress */
459 : /* */
460 : /* Class that given a block of memory compresses the contents */
461 : /* using run length encoding (RLE) as used by Imagine. */
462 : /************************************************************************/
463 :
464 : class HFACompress
465 : {
466 : public:
467 : HFACompress(void *pData, GUInt32 nBlockSize, EPTType eDataType);
468 : ~HFACompress();
469 :
470 : // This is the method that does the work.
471 : bool compressBlock();
472 :
473 : // Static method to allow us to query whether HFA type supported.
474 : static bool QueryDataTypeSupported(EPTType eHFADataType);
475 :
476 : // Get methods - only valid after compressBlock has been called.
477 28 : GByte *getCounts() const
478 : {
479 28 : return m_pCounts;
480 : }
481 :
482 13 : GUInt32 getCountSize() const
483 : {
484 13 : return m_nSizeCounts;
485 : }
486 :
487 28 : GByte *getValues() const
488 : {
489 28 : return m_pValues;
490 : }
491 :
492 13 : GUInt32 getValueSize() const
493 : {
494 13 : return m_nSizeValues;
495 : }
496 :
497 13 : GUInt32 getMin() const
498 : {
499 13 : return m_nMin;
500 : }
501 :
502 13 : GUInt32 getNumRuns() const
503 : {
504 13 : return m_nNumRuns;
505 : }
506 :
507 13 : GByte getNumBits() const
508 : {
509 13 : return m_nNumBits;
510 : }
511 :
512 : private:
513 : static void makeCount(GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount);
514 : GUInt32 findMin(GByte *pNumBits);
515 : GUInt32 valueAsUInt32(GUInt32 index);
516 : void encodeValue(GUInt32 val, GUInt32 repeat);
517 :
518 : void *m_pData;
519 : GUInt32 m_nBlockSize;
520 : GUInt32 m_nBlockCount;
521 : EPTType m_eDataType;
522 : // The number of bits the datatype we are trying to compress takes.
523 : int m_nDataTypeNumBits;
524 :
525 : GByte *m_pCounts;
526 : GByte *m_pCurrCount;
527 : GUInt32 m_nSizeCounts;
528 :
529 : GByte *m_pValues;
530 : GByte *m_pCurrValues;
531 : GUInt32 m_nSizeValues;
532 :
533 : GUInt32 m_nMin;
534 : GUInt32 m_nNumRuns;
535 : // The number of bits needed to compress the range of values in the block.
536 : GByte m_nNumBits;
537 : };
538 :
539 : #endif /* ndef HFA_P_H_INCLUDED */
|