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