/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 |