1 /****************************************************************************** 2 * $Id: hfa_p.h 085ace6b956265eaf2405b298048c59e7a9027cd 2019-10-19 23:19:13 +0200 Even Rouault $ 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 46 #ifdef CPL_LSB 47 # define HFAStandard(n,p) {} 48 #else 49 void HFAStandard( int, void *); 50 #endif 51 52 #include "hfa.h" 53 54 class HFABand; 55 class HFADictionary; 56 class HFAEntry; 57 class HFASpillFile; 58 class HFAType; 59 60 /************************************************************************/ 61 /* Flag indicating read/write, or read-only access to data. */ 62 /************************************************************************/ 63 typedef enum { 64 /*! Read only (no update) access */ HFA_ReadOnly = 0, 65 /*! Read/write access. */ HFA_Update = 1 66 } HFAAccess; 67 68 /************************************************************************/ 69 /* HFAInfo_t */ 70 /* */ 71 /* This is just a structure, and used hold info about the whole */ 72 /* dataset within hfaopen.cpp */ 73 /************************************************************************/ 74 struct hfainfo { 75 VSILFILE *fp; 76 77 char *pszPath; 78 char *pszFilename; // Sans path. 79 char *pszIGEFilename; // Sans path. 80 81 HFAAccess eAccess; 82 83 GUInt32 nEndOfFile; 84 GUInt32 nRootPos; 85 GUInt32 nDictionaryPos; 86 87 GInt16 nEntryHeaderLength; 88 GInt32 nVersion; 89 90 bool bTreeDirty; 91 HFAEntry *poRoot; 92 93 HFADictionary *poDictionary; 94 char *pszDictionary; 95 96 int nXSize; 97 int nYSize; 98 99 int nBands; 100 HFABand **papoBand; 101 102 void *pMapInfo; 103 void *pDatum; 104 void *pProParameters; 105 106 struct hfainfo *psDependent; 107 }; 108 109 typedef struct hfainfo HFAInfo_t; 110 111 GUInt32 HFAAllocateSpace( HFAInfo_t *, GUInt32 ); 112 CPLErr HFAParseBandInfo( HFAInfo_t * ); 113 HFAInfo_t *HFAGetDependent( HFAInfo_t *, const char * ); 114 HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase ); 115 bool HFACreateSpillStack( HFAInfo_t *, int nXSize, int nYSize, int nLayers, 116 int nBlockSize, EPTType eDataType, 117 GIntBig *pnValidFlagsOffset, 118 GIntBig *pnDataOffset ); 119 120 const char * const * GetHFAAuxMetaDataList(); 121 122 double *HFAReadBFUniqueBins( HFAEntry *poBinFunc, int nPCTColors ); 123 124 int CPL_DLL 125 HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent, 126 const char *pszLayerName, 127 int bOverview, int nBlockSize, 128 int bCreateCompressed, int bCreateLargeRaster, 129 int bDependentLayer, 130 int nXSize, int nYSize, EPTType eDataType, 131 char **papszOptions, 132 133 // These are only related to external (large) files. 134 GIntBig nStackValidFlagsOffset, 135 GIntBig nStackDataOffset, 136 int nStackCount, int nStackIndex ); 137 138 char * 139 HFAPCSStructToWKT( const Eprj_Datum *psDatum, 140 const Eprj_ProParameters *psPro, 141 const Eprj_MapInfo *psMapInfo, 142 HFAEntry *poMapInformation ); 143 144 /************************************************************************/ 145 /* HFABand */ 146 /************************************************************************/ 147 148 class HFABand 149 { 150 int nBlocks; 151 152 // Used for single-file modification. 153 vsi_l_offset *panBlockStart; 154 int *panBlockSize; 155 int *panBlockFlag; 156 157 // Used for spill-file modification. 158 vsi_l_offset nBlockStart; 159 vsi_l_offset nBlockSize; 160 int nLayerStackCount; 161 int nLayerStackIndex; 162 163 #define BFLG_VALID 0x01 164 #define BFLG_COMPRESSED 0x02 165 166 int nPCTColors; 167 double *apadfPCT[4]; 168 double *padfPCTBins; 169 170 CPLErr LoadBlockInfo(); 171 CPLErr LoadExternalBlockInfo(); 172 173 void ReAllocBlock( int iBlock, int nSize ); 174 void NullBlock( void * ); 175 176 CPLString osOverName; 177 178 public: 179 HFABand( HFAInfo_t *, HFAEntry * ); 180 ~HFABand(); 181 182 HFAInfo_t *psInfo; 183 184 VSILFILE *fpExternal; 185 186 EPTType eDataType; 187 HFAEntry *poNode; 188 189 int nBlockXSize; 190 int nBlockYSize; 191 192 int nWidth; 193 int nHeight; 194 195 int nBlocksPerRow; 196 int nBlocksPerColumn; 197 198 bool bNoDataSet; 199 double dfNoData; 200 201 bool bOverviewsPending; 202 int nOverviews; 203 HFABand **papoOverviews; 204 205 CPLErr GetRasterBlock( int nXBlock, int nYBlock, void * pData, 206 int nDataSize ); 207 CPLErr SetRasterBlock( int nXBlock, int nYBlock, void * pData ); 208 209 const char * GetBandName(); 210 void SetBandName(const char *pszName); 211 212 CPLErr SetNoDataValue( double dfValue ); 213 214 CPLErr GetPCT( int *, double **, double **, double **, double **, 215 double ** ); 216 CPLErr SetPCT( int, double *, double *, double *, double * ); 217 218 int CreateOverview( int nOverviewLevel, const char *pszResampling ); 219 CPLErr CleanOverviews(); 220 221 CPLErr LoadOverviews(); 222 }; 223 224 /************************************************************************/ 225 /* HFAEntry */ 226 /* */ 227 /* Base class for all entry types. Most entry types do not */ 228 /* have a subclass, and are just handled generically with this */ 229 /* class. */ 230 /************************************************************************/ 231 class HFAEntry 232 { 233 bool bDirty; 234 GUInt32 nFilePos; 235 236 HFAInfo_t *psHFA; 237 HFAEntry *poParent; 238 HFAEntry *poPrev; 239 240 GUInt32 nNextPos; 241 HFAEntry *poNext; 242 243 GUInt32 nChildPos; 244 HFAEntry *poChild; 245 246 char szName[64]; 247 char szType[32]; 248 249 HFAType *poType; 250 251 GUInt32 nDataPos; 252 GUInt32 nDataSize; 253 GByte *pabyData; 254 255 void LoadData(); 256 257 bool GetFieldValue( const char *, char, void *, 258 int *pnRemainingDataSize ); 259 CPLErr SetFieldValue( const char *, char, void * ); 260 261 bool bIsMIFObject; 262 263 HFAEntry(); 264 HFAEntry( const char * pszDictionary, 265 const char * pszTypeName, 266 int nDataSizeIn, 267 GByte* pabyDataIn ); 268 std::vector<HFAEntry*> FindChildren( const char *pszName, 269 const char *pszType, 270 int nRecLevel, 271 int* pbErrorDetected); 272 273 public: 274 static HFAEntry* New( HFAInfo_t * psHFA, GUInt32 nPos, 275 HFAEntry * poParent, 276 HFAEntry *poPrev) CPL_WARN_UNUSED_RESULT; 277 278 HFAEntry( HFAInfo_t *psHFA, 279 const char *pszNodeName, 280 const char *pszTypeName, 281 HFAEntry *poParent ); 282 283 static HFAEntry* New( HFAInfo_t *psHFA, 284 const char *pszNodeName, 285 const char *pszTypeName, 286 HFAEntry *poParent ) CPL_WARN_UNUSED_RESULT; 287 288 virtual ~HFAEntry(); 289 290 static HFAEntry* BuildEntryFromMIFObject( 291 HFAEntry *poContainer, 292 const char *pszMIFObjectPath ) CPL_WARN_UNUSED_RESULT; 293 294 CPLErr RemoveAndDestroy(); 295 GetFilePos()296 GUInt32 GetFilePos() const CPL_WARN_UNUSED_RESULT { return nFilePos; } 297 GetName()298 const char *GetName() const CPL_WARN_UNUSED_RESULT { return szName; } 299 void SetName( const char *pszNodeName ); 300 GetType()301 const char *GetType() const CPL_WARN_UNUSED_RESULT { return szType; } 302 HFAType *GetTypeObject() CPL_WARN_UNUSED_RESULT; 303 GetData()304 GByte *GetData() CPL_WARN_UNUSED_RESULT { LoadData(); return pabyData; } GetDataPos()305 GUInt32 GetDataPos() const CPL_WARN_UNUSED_RESULT { return nDataPos; } GetDataSize()306 GUInt32 GetDataSize() const CPL_WARN_UNUSED_RESULT { return nDataSize; } 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*> FindChildren( const char *pszName, 312 const char *pszType) CPL_WARN_UNUSED_RESULT; 313 314 GInt32 GetIntField( const char *, CPLErr * = nullptr ) CPL_WARN_UNUSED_RESULT; 315 double GetDoubleField( const char *, CPLErr * = nullptr ) CPL_WARN_UNUSED_RESULT; 316 const char *GetStringField( const char *, CPLErr * = nullptr, int *pnRemainingDataSize = nullptr ) CPL_WARN_UNUSED_RESULT; 317 GIntBig GetBigIntField( const char *, CPLErr * = nullptr ) CPL_WARN_UNUSED_RESULT; 318 int GetFieldCount( const char *, CPLErr * = nullptr ) CPL_WARN_UNUSED_RESULT; 319 320 CPLErr SetIntField( const char *, int ); 321 CPLErr SetDoubleField( const char *, double ); 322 CPLErr SetStringField( const char *, const char * ); 323 324 void DumpFieldValues( FILE *, const char * = nullptr ); 325 326 void SetPosition(); 327 CPLErr FlushToDisk(); 328 329 void MarkDirty(); 330 GByte *MakeData( int nSize = 0 ); 331 }; 332 333 /************************************************************************/ 334 /* HFAField */ 335 /* */ 336 /* A field in a HFAType in the dictionary. */ 337 /************************************************************************/ 338 339 class HFAField 340 { 341 public: 342 int nBytes; 343 344 int nItemCount; 345 // TODO(schwehr): Rename chPointer to something more meaningful. 346 // It's not a pointer. 347 char chPointer; // '\0', '*' or 'p' 348 char chItemType; // 1|2|4|e|... 349 350 char *pszItemObjectType; // if chItemType == 'o' 351 HFAType *poItemObjectType; 352 353 char **papszEnumNames; // Normally NULL if not an enum. 354 355 char *pszFieldName; 356 357 char szNumberString[36]; // Buffer used to return int as a string. 358 359 HFAField(); 360 ~HFAField(); 361 362 const char *Initialize( const char * ); 363 364 bool CompleteDefn( HFADictionary * ); 365 366 void Dump( FILE * ); 367 368 bool ExtractInstValue( const char * pszField, int nIndexValue, 369 GByte *pabyData, GUInt32 nDataOffset, 370 int nDataSize, char chReqType, 371 void *pReqReturn, 372 int *pnRemainingDataSize = nullptr ); 373 374 CPLErr SetInstValue( const char * pszField, int nIndexValue, 375 GByte *pabyData, GUInt32 nDataOffset, 376 int nDataSize, 377 char chReqType, void *pValue ); 378 379 void DumpInstValue( FILE *fpOut, GByte *pabyData, 380 GUInt32 nDataOffset, int nDataSize, 381 const char *pszPrefix = nullptr ); 382 383 int GetInstBytes( GByte *, int, std::set<HFAField*>& oVisitedFields ); 384 int GetInstCount( GByte * pabyData, int nDataSize ) const; 385 }; 386 387 /************************************************************************/ 388 /* HFAType */ 389 /* */ 390 /* A type in the dictionary. */ 391 /************************************************************************/ 392 393 class HFAType 394 { 395 bool bInCompleteDefn; 396 397 public: 398 int nBytes; 399 400 std::vector<std::unique_ptr<HFAField>> apoFields; 401 402 char *pszTypeName; 403 404 HFAType(); 405 ~HFAType(); 406 407 const char *Initialize( const char * ); 408 409 bool CompleteDefn( HFADictionary * ); 410 411 void Dump( FILE * ); 412 413 int GetInstBytes( GByte *, int, std::set<HFAField*>& oVisitedFields ) const; 414 int GetInstCount( const char *pszField, GByte *pabyData, 415 GUInt32 nDataOffset, int nDataSize ); 416 bool ExtractInstValue( const char * pszField, 417 GByte *pabyData, GUInt32 nDataOffset, 418 int nDataSize, char chReqType, 419 void *pReqReturn, int *pnRemainingDataSize ); 420 CPLErr SetInstValue( const char * pszField, GByte *pabyData, 421 GUInt32 nDataOffset, int nDataSize, 422 char chReqType, void * pValue ); 423 void DumpInstValue( FILE *fpOut, GByte *pabyData, 424 GUInt32 nDataOffset, int nDataSize, 425 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. getCounts()476 GByte* getCounts() const { return m_pCounts; } getCountSize()477 GUInt32 getCountSize() const { return m_nSizeCounts; } getValues()478 GByte* getValues() const { return m_pValues; } getValueSize()479 GUInt32 getValueSize() const { return m_nSizeValues; } getMin()480 GUInt32 getMin() const { return m_nMin; } getNumRuns()481 GUInt32 getNumRuns() const { return m_nNumRuns; } getNumBits()482 GByte getNumBits() const { return m_nNumBits; } 483 484 private: 485 static void makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount ); 486 GUInt32 findMin( GByte *pNumBits ); 487 GUInt32 valueAsUInt32( GUInt32 index ); 488 void encodeValue( GUInt32 val, GUInt32 repeat ); 489 490 void *m_pData; 491 GUInt32 m_nBlockSize; 492 GUInt32 m_nBlockCount; 493 EPTType m_eDataType; 494 // The number of bits the datatype we are trying to compress takes. 495 int m_nDataTypeNumBits; 496 497 GByte *m_pCounts; 498 GByte *m_pCurrCount; 499 GUInt32 m_nSizeCounts; 500 501 GByte *m_pValues; 502 GByte *m_pCurrValues; 503 GUInt32 m_nSizeValues; 504 505 GUInt32 m_nMin; 506 GUInt32 m_nNumRuns; 507 // The number of bits needed to compress the range of values in the block. 508 GByte m_nNumBits; 509 }; 510 511 #endif /* ndef HFA_P_H_INCLUDED */ 512