Coverage Report

Created: 2025-06-13 06:29

/src/gdal/third_party/LercLib/Huffman.h
Line
Count
Source (jump to first uncovered line)
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 <cstring>
29
#include <utility>
30
#include "Defines.h"
31
32
NAMESPACE_LERC_START
33
34
class Huffman
35
{
36
public:
37
0
  Huffman() : m_maxHistoSize(1 << 15), m_maxNumBitsLUT(12), m_numBitsToSkipInTree(0), m_root(nullptr) {}
38
0
  ~Huffman() { Clear(); }
39
40
  // Limitation: We limit the max Huffman code length to 32 bit. If this happens, the function ComputeCodes()
41
  // returns false. In that case don't use Huffman coding but Lerc only instead.
42
  // This won't happen easily. For the worst case input maximizing the Huffman code length the counts in the
43
  // histogram have to follow the Fibonacci sequence. Even then, for < 9,227,465 data values, 32 bit is
44
  // the max Huffman code length possible.
45
46
  bool ComputeCodes(const std::vector<int>& histo);    // input histogram, size < 2^15
47
48
  bool ComputeCompressedSize(const std::vector<int>& histo, int& numBytes, double& avgBpp) const;
49
50
  // LUT of same size as histogram, each entry has length of Huffman bit code, and the bit code
51
0
  const std::vector<std::pair<unsigned short, unsigned int> >& GetCodes() const  { return m_codeTable; }
52
  bool SetCodes(const std::vector<std::pair<unsigned short, unsigned int> >& codeTable);
53
54
  bool WriteCodeTable(Byte** ppByte, int lerc2Version) const;
55
  bool ReadCodeTable(const Byte** ppByte, size_t& nBytesRemaining, int lerc2Version);
56
57
  bool BuildTreeFromCodes(int& numBitsLUT);
58
  bool DecodeOneValue(const unsigned int** ppSrc, size_t& nBytesRemaining, int& bitPos, int numBitsLUT, int& value) const;
59
  bool DecodeOneValue_NoOverrunCheck(const unsigned int** ppSrc, size_t& nBytesRemaining, int& bitPos, int numBitsLUT, int& value) const;
60
  void Clear();
61
62
private:
63
64
  struct Node
65
  {
66
    int weight;
67
    short value;
68
    Node *child0, *child1;
69
70
    Node(short val, int cnt)    // new leaf node for val
71
0
    {
72
0
      value = val;
73
0
      weight = -cnt;
74
0
      child0 = child1 = nullptr;
75
0
    }
76
77
    Node(Node* c0, Node* c1)    // new internal node from children c0 and c1
78
0
    {
79
0
      value = -1;
80
0
      weight = c0->weight + c1->weight;
81
0
      child0 = c0;
82
0
      child1 = c1;
83
0
    }
84
85
0
    bool operator < (const Node& other) const  { return weight < other.weight; }
86
87
    bool TreeToLUT(unsigned short numBits, unsigned int bits, std::vector<std::pair<unsigned short, unsigned int> >& luTable) const
88
0
    {
89
0
      if (child0)
90
0
      {
91
0
        if (numBits == 32    // the max huffman code length we allow
92
0
          || !child0->TreeToLUT(numBits + 1, (bits << 1) + 0, luTable)
93
0
          || !child1->TreeToLUT(numBits + 1, (bits << 1) + 1, luTable))
94
0
        {
95
0
          return false;
96
0
        }
97
0
      }
98
0
      else
99
0
        luTable[value] = std::pair<unsigned short, unsigned int>(numBits, bits);
100
101
0
      return true;
102
0
    }
103
104
    void FreeTree(int& n)
105
0
    {
106
0
      if (child0)
107
0
      {
108
0
        child0->FreeTree(n);
109
0
        delete child0;
110
0
        child0 = nullptr;
111
0
        n--;
112
0
      }
113
0
      if (child1)
114
0
      {
115
0
        child1->FreeTree(n);
116
0
        delete child1;
117
0
        child1 = nullptr;
118
0
        n--;
119
0
      }
120
0
    }
121
  };
122
123
private:
124
125
  size_t m_maxHistoSize;
126
  std::vector<std::pair<unsigned short, unsigned int> > m_codeTable;
127
  std::vector<std::pair<short, short> > m_decodeLUT;
128
  int m_maxNumBitsLUT;
129
  int m_numBitsToSkipInTree;
130
  Node* m_root;
131
132
0
  static int GetIndexWrapAround(int i, int size)  { return i - (i < size ? 0 : size); }
133
134
  bool ComputeNumBytesCodeTable(int& numBytes) const;
135
  bool GetRange(int& i0, int& i1, int& maxCodeLength) const;
136
  bool BitStuffCodes(Byte** ppByte, int i0, int i1) const;
137
  bool BitUnStuffCodes(const Byte** ppByte, size_t& nBytesRemaining, int i0, int i1);
138
  bool ConvertCodesToCanonical();
139
  void ClearTree();
140
};
141
142
// -------------------------------------------------------------------------- ;
143
144
inline bool Huffman::DecodeOneValue(const unsigned int** ppSrc, size_t& nBytesRemaining, int& bitPos, int numBitsLUT, int& value) const
145
0
{
146
0
  const size_t sizeUInt = sizeof(unsigned int);
147
148
0
  if (!ppSrc || !(*ppSrc) || bitPos < 0 || bitPos >= 32 || nBytesRemaining < sizeUInt)
149
0
    return false;
150
151
  // first get the next (up to) 12 bits as a copy
152
0
  int valTmp = ((**ppSrc) << bitPos) >> (32 - numBitsLUT);
153
0
  if (32 - bitPos < numBitsLUT)
154
0
  {
155
0
    if (nBytesRemaining < 2 * sizeUInt)
156
0
      return false;
157
158
0
    valTmp |= (*(*ppSrc + 1)) >> (64 - bitPos - numBitsLUT);
159
0
  }
160
161
0
  if (m_decodeLUT[valTmp].first >= 0)    // if there, move the correct number of bits and done
162
0
  {
163
0
    value = m_decodeLUT[valTmp].second;
164
0
    bitPos += m_decodeLUT[valTmp].first;
165
0
    if (bitPos >= 32)
166
0
    {
167
0
      bitPos -= 32;
168
0
      (*ppSrc)++;
169
0
      nBytesRemaining -= sizeUInt;
170
0
    }
171
0
    return true;
172
0
  }
173
174
  // if not there, go through the tree (slower)
175
176
0
  if (!m_root)
177
0
    return false;
178
179
  // skip leading 0 bits before entering the tree
180
0
  bitPos += m_numBitsToSkipInTree;
181
0
  if (bitPos >= 32)
182
0
  {
183
0
    bitPos -= 32;
184
0
    (*ppSrc)++;
185
0
    nBytesRemaining -= sizeUInt;
186
0
  }
187
188
0
  const Node* node = m_root;
189
0
  value = -1;
190
0
  while (value < 0 && nBytesRemaining >= sizeUInt)
191
0
  {
192
0
    int bit = ((**ppSrc) << bitPos) >> 31;
193
0
    bitPos++;
194
0
    if (bitPos == 32)
195
0
    {
196
0
      bitPos = 0;
197
0
      (*ppSrc)++;
198
0
      nBytesRemaining -= sizeUInt;
199
0
    }
200
201
0
    node = bit ? node->child1 : node->child0;
202
0
    if (!node)
203
0
      return false;
204
205
0
    if (node->value >= 0)    // reached a leaf node
206
0
      value = node->value;
207
0
  }
208
209
0
  return (value >= 0);
210
0
}
211
212
// -------------------------------------------------------------------------- ;
213
214
inline bool Huffman::DecodeOneValue_NoOverrunCheck(const unsigned int** ppSrc, size_t& nBytesRemaining, int& bitPos, int numBitsLUT, int& value) const
215
0
{
216
0
  const size_t sizeUInt = sizeof(unsigned int);
217
218
0
  if (!ppSrc || !(*ppSrc) || bitPos < 0 || bitPos >= 32)
219
0
    return false;
220
221
  // first get the next (up to) 12 bits as a copy
222
0
  int valTmp = ((**ppSrc) << bitPos) >> (32 - numBitsLUT);
223
0
  if (32 - bitPos < numBitsLUT)
224
0
  {
225
0
    valTmp |= (*(*ppSrc + 1)) >> (64 - bitPos - numBitsLUT);
226
0
  }
227
228
0
  if (m_decodeLUT[valTmp].first >= 0)    // if there, move the correct number of bits and done
229
0
  {
230
0
    value = m_decodeLUT[valTmp].second;
231
0
    bitPos += m_decodeLUT[valTmp].first;
232
0
    if (bitPos >= 32)
233
0
    {
234
0
      bitPos -= 32;
235
0
      (*ppSrc)++;
236
0
      nBytesRemaining -= sizeUInt;
237
0
    }
238
0
    return true;
239
0
  }
240
241
  // if not there, go through the tree (slower)
242
243
0
  if (!m_root)
244
0
    return false;
245
246
  // skip leading 0 bits before entering the tree
247
0
  bitPos += m_numBitsToSkipInTree;
248
0
  if (bitPos >= 32)
249
0
  {
250
0
    bitPos -= 32;
251
0
    (*ppSrc)++;
252
0
    nBytesRemaining -= sizeUInt;
253
0
  }
254
255
0
  const Node* node = m_root;
256
0
  value = -1;
257
0
  while (value < 0)
258
0
  {
259
0
    int bit = ((**ppSrc) << bitPos) >> 31;
260
0
    bitPos++;
261
0
    if (bitPos == 32)
262
0
    {
263
0
      bitPos = 0;
264
0
      (*ppSrc)++;
265
0
      nBytesRemaining -= sizeUInt;
266
0
    }
267
268
0
    node = bit ? node->child1 : node->child0;
269
0
    if (!node)
270
0
      return false;
271
272
0
    if (node->value >= 0)    // reached a leaf node
273
0
      value = node->value;
274
0
  }
275
276
0
  return (value >= 0);
277
0
}
278
279
// -------------------------------------------------------------------------- ;
280
281
NAMESPACE_LERC_END
282
#endif