/src/gdal/frmts/hfa/hfa_p.h
Line | Count | Source |
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 | 13.0M | { \ |
33 | 13.0M | } |
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 final |
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 | 146k | #define BFLG_VALID 0x01 |
150 | 143k | #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 | | CPL_DISALLOW_COPY_ASSIGN(HFABand) |
165 | | |
166 | | public: |
167 | | HFABand(HFAInfo_t *, HFAEntry *); |
168 | | ~HFABand(); |
169 | | |
170 | | HFAInfo_t *psInfo; |
171 | | |
172 | | VSILFILE *fpExternal; |
173 | | |
174 | | EPTType eDataType; |
175 | | HFAEntry *poNode; |
176 | | |
177 | | int nBlockXSize; |
178 | | int nBlockYSize; |
179 | | |
180 | | int nWidth; |
181 | | int nHeight; |
182 | | |
183 | | int nBlocksPerRow; |
184 | | int nBlocksPerColumn; |
185 | | |
186 | | bool bNoDataSet; |
187 | | double dfNoData; |
188 | | |
189 | | bool bOverviewsPending; |
190 | | int nOverviews; |
191 | | HFABand **papoOverviews; |
192 | | |
193 | | CPLErr GetRasterBlock(int nXBlock, int nYBlock, void *pData, int nDataSize); |
194 | | CPLErr SetRasterBlock(int nXBlock, int nYBlock, void *pData); |
195 | | |
196 | | const char *GetBandName(); |
197 | | void SetBandName(const char *pszName); |
198 | | |
199 | | CPLErr SetNoDataValue(double dfValue); |
200 | | |
201 | | CPLErr GetPCT(int *, double **, double **, double **, double **, double **); |
202 | | CPLErr SetPCT(int, const double *, const double *, const double *, |
203 | | const double *); |
204 | | |
205 | | int CreateOverview(int nOverviewLevel, const char *pszResampling); |
206 | | CPLErr CleanOverviews(); |
207 | | |
208 | | CPLErr LoadOverviews(); |
209 | | }; |
210 | | |
211 | | /************************************************************************/ |
212 | | /* HFAEntry */ |
213 | | /* */ |
214 | | /* Base class for all entry types. Most entry types do not */ |
215 | | /* have a subclass, and are just handled generically with this */ |
216 | | /* class. */ |
217 | | /************************************************************************/ |
218 | | class HFAEntry final |
219 | | { |
220 | | bool bDirty; |
221 | | GUInt32 nFilePos; |
222 | | |
223 | | HFAInfo_t *psHFA; |
224 | | HFAEntry *poParent; |
225 | | HFAEntry *poPrev; |
226 | | |
227 | | GUInt32 nNextPos; |
228 | | HFAEntry *poNext; |
229 | | |
230 | | GUInt32 nChildPos; |
231 | | HFAEntry *poChild; |
232 | | |
233 | | char szName[64]; |
234 | | char szType[32]; |
235 | | |
236 | | HFAType *poType; |
237 | | |
238 | | GUInt32 nDataPos; |
239 | | GUInt32 nDataSize; |
240 | | GByte *pabyData; |
241 | | |
242 | | void LoadData(); |
243 | | |
244 | | bool GetFieldValue(const char *, char, void *, int *pnRemainingDataSize); |
245 | | CPLErr SetFieldValue(const char *, char, void *); |
246 | | |
247 | | bool bIsMIFObject; |
248 | | |
249 | | HFAEntry(); |
250 | | HFAEntry(const char *pszDictionary, const char *pszTypeName, |
251 | | int nDataSizeIn, GByte *pabyDataIn); |
252 | | std::vector<HFAEntry *> FindChildren(const char *pszName, |
253 | | const char *pszType, int nRecLevel, |
254 | | int *pbErrorDetected); |
255 | | |
256 | | CPL_DISALLOW_COPY_ASSIGN(HFAEntry) |
257 | | |
258 | | public: |
259 | | static HFAEntry *New(HFAInfo_t *psHFA, GUInt32 nPos, HFAEntry *poParent, |
260 | | HFAEntry *poPrev) CPL_WARN_UNUSED_RESULT; |
261 | | |
262 | | HFAEntry(HFAInfo_t *psHFA, const char *pszNodeName, const char *pszTypeName, |
263 | | HFAEntry *poParent); |
264 | | |
265 | | static HFAEntry *New(HFAInfo_t *psHFA, const char *pszNodeName, |
266 | | const char *pszTypeName, |
267 | | HFAEntry *poParent) CPL_WARN_UNUSED_RESULT; |
268 | | |
269 | | ~HFAEntry(); |
270 | | |
271 | | static HFAEntry *BuildEntryFromMIFObject(HFAEntry *poContainer, |
272 | | const char *pszMIFObjectPath) |
273 | | CPL_WARN_UNUSED_RESULT; |
274 | | |
275 | | CPLErr RemoveAndDestroy(); |
276 | | |
277 | | GUInt32 GetFilePos() const CPL_WARN_UNUSED_RESULT |
278 | 367 | { |
279 | 367 | return nFilePos; |
280 | 367 | } |
281 | | |
282 | | const char *GetName() const CPL_WARN_UNUSED_RESULT |
283 | 2.78M | { |
284 | 2.78M | return szName; |
285 | 2.78M | } |
286 | | |
287 | | void SetName(const char *pszNodeName); |
288 | | |
289 | | const char *GetType() const CPL_WARN_UNUSED_RESULT |
290 | 995k | { |
291 | 995k | return szType; |
292 | 995k | } |
293 | | |
294 | | HFAType *GetTypeObject() CPL_WARN_UNUSED_RESULT; |
295 | | |
296 | | GByte *GetData() CPL_WARN_UNUSED_RESULT |
297 | 18.7k | { |
298 | 18.7k | LoadData(); |
299 | 18.7k | return pabyData; |
300 | 18.7k | } |
301 | | |
302 | | GUInt32 GetDataPos() const CPL_WARN_UNUSED_RESULT |
303 | 18.9k | { |
304 | 18.9k | return nDataPos; |
305 | 18.9k | } |
306 | | |
307 | | GUInt32 GetDataSize() const CPL_WARN_UNUSED_RESULT |
308 | 18.7k | { |
309 | 18.7k | return nDataSize; |
310 | 18.7k | } |
311 | | |
312 | | HFAEntry *GetChild() CPL_WARN_UNUSED_RESULT; |
313 | | HFAEntry *GetNext() CPL_WARN_UNUSED_RESULT; |
314 | | HFAEntry *GetNamedChild(const char *) CPL_WARN_UNUSED_RESULT; |
315 | | std::vector<HFAEntry *> |
316 | | FindChildren(const char *pszName, |
317 | | const char *pszType) CPL_WARN_UNUSED_RESULT; |
318 | | |
319 | | GInt32 GetIntField(const char *, CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT; |
320 | | double GetDoubleField(const char *, |
321 | | CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT; |
322 | | const char * |
323 | | GetStringField(const char *, CPLErr * = nullptr, |
324 | | int *pnRemainingDataSize = nullptr) CPL_WARN_UNUSED_RESULT; |
325 | | GIntBig GetBigIntField(const char *, |
326 | | CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT; |
327 | | int GetFieldCount(const char *, CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT; |
328 | | |
329 | | CPLErr SetIntField(const char *, int); |
330 | | CPLErr SetDoubleField(const char *, double); |
331 | | CPLErr SetStringField(const char *, const char *); |
332 | | |
333 | | void DumpFieldValues(FILE *, const char * = nullptr); |
334 | | |
335 | | void SetPosition(); |
336 | | CPLErr FlushToDisk(); |
337 | | |
338 | | void MarkDirty(); |
339 | | GByte *MakeData(int nSize = 0); |
340 | | }; |
341 | | |
342 | | /************************************************************************/ |
343 | | /* HFAField */ |
344 | | /* */ |
345 | | /* A field in a HFAType in the dictionary. */ |
346 | | /************************************************************************/ |
347 | | |
348 | | class HFAField final |
349 | | { |
350 | | public: |
351 | | int nBytes; |
352 | | |
353 | | int nItemCount; |
354 | | // TODO(schwehr): Rename chPointer to something more meaningful. |
355 | | // It's not a pointer. |
356 | | char chPointer; // '\0', '*' or 'p' |
357 | | char chItemType; // 1|2|4|e|... |
358 | | |
359 | | char *pszItemObjectType; // if chItemType == 'o' |
360 | | HFAType *poItemObjectType; |
361 | | |
362 | | char **papszEnumNames; // Normally NULL if not an enum. |
363 | | |
364 | | char *pszFieldName; |
365 | | |
366 | | char szNumberString[36]; // Buffer used to return int as a string. |
367 | | |
368 | | HFAField(); |
369 | | ~HFAField(); |
370 | | |
371 | | const char *Initialize(const char *); |
372 | | |
373 | | bool CompleteDefn(HFADictionary *); |
374 | | |
375 | | void Dump(FILE *); |
376 | | |
377 | | bool ExtractInstValue(const char *pszField, int nIndexValue, |
378 | | GByte *pabyData, GUInt32 nDataOffset, int nDataSize, |
379 | | char chReqType, void *pReqReturn, |
380 | | int *pnRemainingDataSize = nullptr); |
381 | | |
382 | | CPLErr SetInstValue(const char *pszField, int nIndexValue, GByte *pabyData, |
383 | | GUInt32 nDataOffset, int nDataSize, char chReqType, |
384 | | void *pValue); |
385 | | |
386 | | void DumpInstValue(FILE *fpOut, GByte *pabyData, GUInt32 nDataOffset, |
387 | | int nDataSize, const char *pszPrefix = nullptr); |
388 | | |
389 | | int GetInstBytes(GByte *, int, std::set<HFAField *> &oVisitedFields); |
390 | | int GetInstCount(GByte *pabyData, int nDataSize) const; |
391 | | }; |
392 | | |
393 | | /************************************************************************/ |
394 | | /* HFAType */ |
395 | | /* */ |
396 | | /* A type in the dictionary. */ |
397 | | /************************************************************************/ |
398 | | |
399 | | class HFAType |
400 | | { |
401 | | bool bInCompleteDefn; |
402 | | |
403 | | public: |
404 | | int nBytes; |
405 | | |
406 | | std::vector<std::unique_ptr<HFAField>> apoFields; |
407 | | |
408 | | char *pszTypeName; |
409 | | |
410 | | HFAType(); |
411 | | ~HFAType(); |
412 | | |
413 | | const char *Initialize(const char *); |
414 | | |
415 | | bool CompleteDefn(HFADictionary *); |
416 | | |
417 | | void Dump(FILE *); |
418 | | |
419 | | int GetInstBytes(GByte *, int, std::set<HFAField *> &oVisitedFields) const; |
420 | | int GetInstCount(const char *pszField, GByte *pabyData, GUInt32 nDataOffset, |
421 | | int nDataSize); |
422 | | bool ExtractInstValue(const char *pszField, GByte *pabyData, |
423 | | GUInt32 nDataOffset, int nDataSize, char chReqType, |
424 | | void *pReqReturn, int *pnRemainingDataSize); |
425 | | CPLErr SetInstValue(const char *pszField, GByte *pabyData, |
426 | | GUInt32 nDataOffset, int nDataSize, char chReqType, |
427 | | void *pValue); |
428 | | void DumpInstValue(FILE *fpOut, GByte *pabyData, GUInt32 nDataOffset, |
429 | | int nDataSize, const char *pszPrefix = nullptr) const; |
430 | | }; |
431 | | |
432 | | /************************************************************************/ |
433 | | /* HFADictionary */ |
434 | | /************************************************************************/ |
435 | | |
436 | | class HFADictionary |
437 | | { |
438 | | public: |
439 | | explicit HFADictionary(const char *pszDict); |
440 | | ~HFADictionary(); |
441 | | |
442 | | HFAType *FindType(const char *); |
443 | | void AddType(HFAType *); |
444 | | |
445 | | static int GetItemSize(char); |
446 | | |
447 | | void Dump(FILE *); |
448 | | |
449 | | private: |
450 | | int nTypes; |
451 | | int nTypesMax; |
452 | | HFAType **papoTypes; |
453 | | |
454 | | CPL_DISALLOW_COPY_ASSIGN(HFADictionary) |
455 | | |
456 | | public: |
457 | | // TODO(schwehr): Make these members private. |
458 | | CPLString osDictionaryText; |
459 | | bool bDictionaryTextDirty; |
460 | | }; |
461 | | |
462 | | /************************************************************************/ |
463 | | /* HFACompress */ |
464 | | /* */ |
465 | | /* Class that given a block of memory compresses the contents */ |
466 | | /* using run length encoding (RLE) as used by Imagine. */ |
467 | | /************************************************************************/ |
468 | | |
469 | | class HFACompress |
470 | | { |
471 | | public: |
472 | | HFACompress(void *pData, GUInt32 nBlockSize, EPTType eDataType); |
473 | | ~HFACompress(); |
474 | | |
475 | | // This is the method that does the work. |
476 | | bool compressBlock(); |
477 | | |
478 | | // Static method to allow us to query whether HFA type supported. |
479 | | static bool QueryDataTypeSupported(EPTType eHFADataType); |
480 | | |
481 | | // Get methods - only valid after compressBlock has been called. |
482 | | GByte *getCounts() const |
483 | 8 | { |
484 | 8 | return m_pCounts; |
485 | 8 | } |
486 | | |
487 | | GUInt32 getCountSize() const |
488 | 4 | { |
489 | 4 | return m_nSizeCounts; |
490 | 4 | } |
491 | | |
492 | | GByte *getValues() const |
493 | 8 | { |
494 | 8 | return m_pValues; |
495 | 8 | } |
496 | | |
497 | | GUInt32 getValueSize() const |
498 | 4 | { |
499 | 4 | return m_nSizeValues; |
500 | 4 | } |
501 | | |
502 | | GUInt32 getMin() const |
503 | 4 | { |
504 | 4 | return m_nMin; |
505 | 4 | } |
506 | | |
507 | | GUInt32 getNumRuns() const |
508 | 4 | { |
509 | 4 | return m_nNumRuns; |
510 | 4 | } |
511 | | |
512 | | GByte getNumBits() const |
513 | 4 | { |
514 | 4 | return m_nNumBits; |
515 | 4 | } |
516 | | |
517 | | private: |
518 | | static void makeCount(GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount); |
519 | | GUInt32 findMin(GByte *pNumBits); |
520 | | GUInt32 valueAsUInt32(GUInt32 index); |
521 | | void encodeValue(GUInt32 val, GUInt32 repeat); |
522 | | |
523 | | void *m_pData; |
524 | | GUInt32 m_nBlockSize; |
525 | | GUInt32 m_nBlockCount; |
526 | | EPTType m_eDataType; |
527 | | // The number of bits the datatype we are trying to compress takes. |
528 | | int m_nDataTypeNumBits; |
529 | | |
530 | | GByte *m_pCounts; |
531 | | GByte *m_pCurrCount; |
532 | | GUInt32 m_nSizeCounts; |
533 | | |
534 | | GByte *m_pValues; |
535 | | GByte *m_pCurrValues; |
536 | | GUInt32 m_nSizeValues; |
537 | | |
538 | | GUInt32 m_nMin; |
539 | | GUInt32 m_nNumRuns; |
540 | | // The number of bits needed to compress the range of values in the block. |
541 | | GByte m_nNumBits; |
542 | | }; |
543 | | |
544 | | #endif /* ndef HFA_P_H_INCLUDED */ |