Huffman.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #ifndef CRYINCLUDE_CRYSYSTEM_HUFFMAN_H
  9. #define CRYINCLUDE_CRYSYSTEM_HUFFMAN_H
  10. #pragma once
  11. class HuffmanCoder
  12. {
  13. private:
  14. struct HuffmanTreeNode
  15. {
  16. uint32 count;
  17. uint32 savedCount;
  18. int child0;
  19. int child1;
  20. };
  21. struct HuffmanSymbolCode
  22. {
  23. uint32 value;
  24. uint32 numBits;
  25. };
  26. struct BitStreamBuilder
  27. {
  28. enum EModes
  29. {
  30. eM_WRITE,
  31. eM_READ
  32. };
  33. union buf_ptr
  34. {
  35. uint8* ptr;
  36. const uint8* const_ptr;
  37. };
  38. EModes m_mode;
  39. uint8 m_mask;
  40. buf_ptr m_pBufferStart;
  41. buf_ptr m_pBufferCursor;
  42. buf_ptr m_pBufferEnd; //Pointer to the last byte in the buffer
  43. BitStreamBuilder(uint8* pBufferStart, uint8* pBufferEnd)
  44. : m_mode(eM_WRITE)
  45. , m_mask(0x80)
  46. {
  47. m_pBufferStart.ptr = pBufferStart;
  48. m_pBufferCursor.ptr = pBufferStart;
  49. m_pBufferEnd.ptr = pBufferEnd;
  50. }
  51. BitStreamBuilder(const uint8* pBufferStart, const uint8* pBufferEnd)
  52. : m_mode(eM_READ)
  53. , m_mask(0x80)
  54. {
  55. m_pBufferStart.const_ptr = pBufferStart;
  56. m_pBufferCursor.const_ptr = pBufferStart;
  57. m_pBufferEnd.const_ptr = pBufferEnd;
  58. }
  59. void AddBits(uint32 value, uint32 numBits);
  60. void AddBits(uint8 value, uint32 numBits);
  61. //Returns 1 or 0 for valid values. Returns 2 if the buffer has run out or is the wrong type of builder.
  62. uint8 GetBit();
  63. };
  64. const static int MAX_SYMBOL_VALUE = (255);
  65. const static int MAX_NUM_SYMBOLS = (MAX_SYMBOL_VALUE + 1);
  66. const static int END_OF_STREAM = (MAX_NUM_SYMBOLS);
  67. const static int MAX_NUM_CODES = (MAX_NUM_SYMBOLS + 1);
  68. const static int MAX_NUM_NODES = (MAX_NUM_CODES * 2);
  69. const static int MAX_NODE = (MAX_NUM_NODES - 1);
  70. enum EHuffmanCoderState
  71. {
  72. eHCS_NEW, //Has been created, Init not called
  73. eHCS_OPEN, //Init has been called, tree not yet constructed. Can accept new data.
  74. eHCS_FINAL //Finalize has been called. Can no longer accept data, but can encode/decode.
  75. };
  76. HuffmanTreeNode* m_TreeNodes;
  77. HuffmanSymbolCode* m_Codes;
  78. uint32* m_Counts;
  79. int m_RootNode;
  80. uint32 m_RefCount;
  81. EHuffmanCoderState m_State;
  82. public:
  83. HuffmanCoder()
  84. : m_TreeNodes(NULL)
  85. , m_Codes(NULL)
  86. , m_Counts(NULL)
  87. , m_State(eHCS_NEW)
  88. , m_RootNode(0)
  89. , m_RefCount(0) {}
  90. ~HuffmanCoder()
  91. {
  92. SAFE_DELETE_ARRAY(m_TreeNodes);
  93. SAFE_DELETE_ARRAY(m_Codes);
  94. SAFE_DELETE_ARRAY(m_Counts);
  95. }
  96. //A bit like an MD5 generator, has three phases.
  97. //Clears the existing data
  98. void Init();
  99. //Adds the values of an array of chars to the counts
  100. void Update(const uint8* const pSource, const size_t numBytes);
  101. //Construct the coding tree using the counts
  102. void Finalize();
  103. //We typically create a Huffman Coder per localized string table loaded. Since we can and do unload strings at runtime, it's useful to keep a ref count of each coder.
  104. inline void AddRef() { m_RefCount++; }
  105. inline void DecRef() { m_RefCount = m_RefCount > 0 ? m_RefCount - 1 : 0; }
  106. inline uint32 RefCount() { return m_RefCount; }
  107. void CompressInput(const uint8* const pInput, const size_t numBytes, uint8* const pOutput, size_t* const outputSize);
  108. size_t UncompressInput(const uint8* const pInput, const size_t numBytes, uint8* const pOutput, const size_t maxOutputSize);
  109. private:
  110. void ScaleCountsAndUpdateNodes();
  111. int BuildTree();
  112. void ConvertTreeToCode(const HuffmanTreeNode* const pNodes, HuffmanSymbolCode* const pCodes, const unsigned int value, const unsigned int numBits, const int node);
  113. };
  114. #endif // CRYINCLUDE_CRYSYSTEM_HUFFMAN_H