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