Coverage Report

Created: 2026-07-25 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/third_party/LercLib/Huffman.h
Line
Count
Source
1
/*
2
Copyright 2015 Esri
3
4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7
8
http://www.apache.org/licenses/LICENSE-2.0
9
10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
16
A local copy of the license and additional notices are located with the
17
source distribution at:
18
19
http://github.com/Esri/lerc/
20
21
Contributors:  Thomas Maurer
22
*/
23
24
#ifndef HUFFMAN_H
25
#define HUFFMAN_H
26
27
#include <vector>
28
#include <cassert>
29
#include <cstring>
30
#include <utility>
31
#include "Defines.h"
32
33
NAMESPACE_LERC_START
34
35
class Huffman
36
{
37
public:
38
0
  Huffman() : m_maxHistoSize(1 << 15), m_maxNumBitsLUT(12), m_numBitsToSkipInTree(0), m_root(nullptr) {}
39
0
  ~Huffman() { Clear(); }
40
41
  // Limitation: We limit the max Huffman code length to 32 bit. If this happens, the function ComputeCodes()
42
  // returns false. In that case don't use Huffman coding but Lerc only instead.
43
  // This won't happen easily. For the worst case input maximizing the Huffman code length the counts in the
44
  // histogram have to follow the Fibonacci sequence. Even then, for < 9,227,465 data values, 32 bit is
45
  // the max Huffman code length possible.
46
47
  bool ComputeCodes(const std::vector<int>& histo);    // input histogram, size < 2^15
48
49
  bool ComputeCompressedSize(const std::vector<int>& histo, int& numBytes, double& avgBpp) const;
50
51
  // LUT of same size as histogram, each entry has length of Huffman bit code, and the bit code
52
0
  const std::vector<std::pair<unsigned short, unsigned int> >& GetCodes() const  { return m_codeTable; }
53
  bool SetCodes(const std::vector<std::pair<unsigned short, unsigned int> >& codeTable);
54
55
  bool WriteCodeTable(Byte** ppByte, int lerc2Version) const;
56
  bool ReadCodeTable(const Byte** ppByte, size_t& nBytesRemaining, int lerc2Version);
57
58
  bool BuildTreeFromCodes(int& numBitsLUT);
59
  inline bool DecodeOneValue(const Byte** ppSrc, size_t& nBytesRemaining, int& bitPos, int numBitsLUT, int& value) const;
60
  inline static bool PushValue(Byte** ppByte, int& bitPos, unsigned int value, int len);
61
  void Clear();
62
63
private:
64
65
  struct Node
66
  {
67
    int weight;
68
    short value;
69
    Node *child0, *child1;
70
71
    Node(short val, int cnt)    // new leaf node for val
72
0
    {
73
0
      value = val;
74
0
      weight = -cnt;
75
0
      child0 = child1 = nullptr;
76
0
    }
77
78
    Node(Node* c0, Node* c1)    // new internal node from children c0 and c1
79
0
    {
80
0
      value = -1;
81
0
      weight = c0->weight + c1->weight;
82
0
      child0 = c0;
83
0
      child1 = c1;
84
0
    }
85
86
0
    bool operator < (const Node& other) const  { return weight < other.weight; }
87
88
    bool TreeToLUT(unsigned short numBits, unsigned int bits, std::vector<std::pair<unsigned short, unsigned int> >& luTable) const
89
0
    {
90
0
      if (child0)
91
0
      {
92
0
        if (numBits == 32    // the max huffman code length we allow
93
0
          || !child0->TreeToLUT(numBits + 1, (bits << 1) + 0, luTable)
94
0
          || !child1->TreeToLUT(numBits + 1, (bits << 1) + 1, luTable))
95
0
        {
96
0
          return false;
97
0
        }
98
0
      }
99
0
      else
100
0
        luTable[value] = std::pair<unsigned short, unsigned int>(numBits, bits);
101
102
0
      return true;
103
0
    }
104
105
    void FreeTree(int& n)
106
0
    {
107
0
      if (child0)
108
0
      {
109
0
        child0->FreeTree(n);
110
0
        delete child0;
111
0
        child0 = nullptr;
112
0
        n--;
113
0
      }
114
0
      if (child1)
115
0
      {
116
0
        child1->FreeTree(n);
117
0
        delete child1;
118
0
        child1 = nullptr;
119
0
        n--;
120
0
      }
121
0
    }
122
  };
123
124
private:
125
126
  size_t m_maxHistoSize;
127
  std::vector<std::pair<unsigned short, unsigned int> > m_codeTable;
128
  std::vector<std::pair<short, short> > m_decodeLUT;
129
  int m_maxNumBitsLUT;
130
  int m_numBitsToSkipInTree;
131
  Node* m_root;
132
133
0
  static int GetIndexWrapAround(int i, int size)  { return i - (i < size ? 0 : size); }
134
135
  bool ComputeNumBytesCodeTable(int& numBytes) const;
136
  bool GetRange(int& i0, int& i1, int& maxCodeLength) const;
137
  bool BitStuffCodes(Byte** ppByte, int i0, int i1) const;
138
  bool BitUnStuffCodes(const Byte** ppByte, size_t& nBytesRemaining, int i0, int i1);
139
  bool ConvertCodesToCanonical();
140
  void ClearTree();
141
};
142
143
// -------------------------------------------------------------------------- ;
144
145
inline bool Huffman::DecodeOneValue(const Byte** ppSrc, size_t& nBytesRemaining, int& bitPos, int numBitsLUT, int& value) const
146
0
{
147
0
  const size_t s4 = sizeof(unsigned int);
148
149
0
  if (!ppSrc || !(*ppSrc) || bitPos < 0 || bitPos >= 32 || nBytesRemaining < s4)
150
0
    return false;
151
152
  // first get the next (up to) 12 bits as a copy
153
0
  unsigned int temp(0);
154
0
  memcpy(&temp, *ppSrc, s4);
155
0
  int valTmp = (temp << bitPos) >> (32 - numBitsLUT);
156
157
0
  if (32 - bitPos < numBitsLUT)
158
0
  {
159
0
    if (nBytesRemaining < 2 * s4)
160
0
      return false;
161
162
0
    memcpy(&temp, *ppSrc + s4, s4);
163
0
    valTmp |= temp >> (64 - bitPos - numBitsLUT);
164
0
  }
165
166
0
  if (m_decodeLUT[valTmp].first >= 0)    // if there, move the correct number of bits and done
167
0
  {
168
0
    value = m_decodeLUT[valTmp].second;
169
0
    bitPos += m_decodeLUT[valTmp].first;
170
0
    if (bitPos >= 32)
171
0
    {
172
0
      bitPos -= 32;
173
0
      *ppSrc += s4;
174
0
      nBytesRemaining -= s4;
175
0
    }
176
0
    return true;
177
0
  }
178
179
  // if not there, go through the tree (slower)
180
181
0
  if (!m_root)
182
0
    return false;
183
184
  // skip leading 0 bits before entering the tree
185
0
  bitPos += m_numBitsToSkipInTree;
186
0
  if (bitPos >= 32)
187
0
  {
188
0
    bitPos -= 32;
189
0
    *ppSrc += s4;
190
0
    nBytesRemaining -= s4;
191
0
  }
192
193
0
  const Node* node = m_root;
194
0
  value = -1;
195
0
  while (value < 0 && nBytesRemaining >= s4)
196
0
  {
197
0
    memcpy(&temp, *ppSrc, s4);
198
0
    int bit = (temp << bitPos) >> 31;
199
0
    bitPos++;
200
0
    if (bitPos == 32)
201
0
    {
202
0
      bitPos = 0;
203
0
      *ppSrc += s4;
204
0
      nBytesRemaining -= s4;
205
0
    }
206
207
0
    node = bit ? node->child1 : node->child0;
208
0
    if (!node)
209
0
      return false;
210
211
0
    if (node->value >= 0)    // reached a leaf node
212
0
      value = node->value;
213
0
  }
214
215
0
  return (value >= 0);
216
0
}
217
218
// -------------------------------------------------------------------------- ;
219
220
inline bool Huffman::PushValue(Byte** ppByte, int& bitPos, unsigned int value, int len)
221
0
{
222
0
  const size_t s4 = sizeof(unsigned int);
223
224
0
  if (!ppByte || !(*ppByte) || bitPos < 0 || bitPos >= 32 || len < 0 || len > 32)
225
0
    return false;
226
227
0
  if (32 - bitPos >= len)
228
0
  {
229
0
    if (bitPos == 0)
230
0
      memset(*ppByte, 0, s4);
231
232
0
    unsigned int temp(0);
233
0
    memcpy(&temp, *ppByte, s4);
234
0
    temp |= value << (32 - bitPos - len);
235
0
    memcpy(*ppByte, &temp, s4);
236
237
0
    bitPos += len;
238
0
    if (bitPos == 32)
239
0
    {
240
0
      bitPos = 0;
241
0
      *ppByte += s4;
242
0
    }
243
0
  }
244
0
  else
245
0
  {
246
0
    bitPos += len - 32;
247
0
    assert(bitPos >= 0); // to make Coverity Scan happy
248
0
    unsigned int temp(0);
249
0
    memcpy(&temp, *ppByte, s4);
250
0
    temp |= value >> bitPos;
251
0
    memcpy(*ppByte, &temp, s4);
252
0
    *ppByte += s4;
253
0
    temp = value << (32 - bitPos);
254
0
    memcpy(*ppByte, &temp, s4);
255
0
  }
256
257
0
  return true;
258
0
}
259
260
// -------------------------------------------------------------------------- ;
261
262
NAMESPACE_LERC_END
263
#endif