1 /*
2 Copyright 2016 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/lepcc/
20
21 Contributors: Thomas Maurer
22 */
23
24 #include <algorithm>
25 #include "BitStuffer2.h"
26
27 using namespace std;
28 using namespace lepcc;
29
30 // -------------------------------------------------------------------------- ;
31
32 // if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
33
EncodeSimple(Byte ** ppByte,const vector<unsigned int> & dataVec) const34 bool BitStuffer2::EncodeSimple(Byte** ppByte, const vector<unsigned int>& dataVec) const
35 {
36 if (!ppByte || dataVec.empty())
37 return false;
38
39 unsigned int maxElem = *max_element(dataVec.begin(), dataVec.end());
40 int numBits = 0;
41 while ((numBits < 32) && (maxElem >> numBits))
42 numBits++;
43
44 if (numBits >= 32)
45 return false;
46
47 Byte numBitsByte = (Byte)numBits;
48 unsigned int numElements = (unsigned int)dataVec.size();
49 unsigned int numUInts = (numElements * numBits + 31) / 32;
50
51 // use the upper 2 bits to encode the type used for numElements: Byte, ushort, or uint
52 int nb = NumBytesUInt(numElements);
53 int bits67 = (nb == 4) ? 0 : 3 - nb;
54 numBitsByte |= bits67 << 6;
55
56 // bit5 = 0 means simple mode
57
58 **ppByte = numBitsByte;
59 (*ppByte)++;
60
61 if (!EncodeUInt(ppByte, numElements, nb))
62 return false;
63
64 if (numUInts > 0) // numBits can be 0, then we only write the header
65 BitStuff(ppByte, dataVec, numBits);
66
67 return true;
68 }
69
70 // -------------------------------------------------------------------------- ;
71
EncodeLut(Byte ** ppByte,const vector<pair<unsigned int,unsigned int>> & sortedDataVec) const72 bool BitStuffer2::EncodeLut(Byte** ppByte, const vector<pair<unsigned int, unsigned int> >& sortedDataVec) const
73 {
74 if (!ppByte || sortedDataVec.empty())
75 return false;
76
77 if (sortedDataVec[0].first != 0) // corresponds to min
78 return false;
79
80 // collect the different values for the lut
81 unsigned int numElem = (unsigned int)sortedDataVec.size();
82 unsigned int indexLut = 0;
83
84 m_tmpLutVec.resize(0); // omit the 0 throughout that corresponds to min
85 m_tmpIndexVec.resize(numElem);
86 memset(&m_tmpIndexVec[0], 0, numElem * sizeof(unsigned int));
87
88 for (unsigned int i = 1; i < numElem; i++)
89 {
90 unsigned int prev = sortedDataVec[i - 1].first;
91 m_tmpIndexVec[sortedDataVec[i - 1].second] = indexLut;
92
93 if (sortedDataVec[i].first != prev)
94 {
95 m_tmpLutVec.push_back(sortedDataVec[i].first);
96 indexLut++;
97 }
98 }
99 m_tmpIndexVec[sortedDataVec[numElem - 1].second] = indexLut; // don't forget the last one
100
101 // write first 2 data elements same as simple, but bit5 set to 1
102 unsigned int maxElem = m_tmpLutVec.back();
103 int numBits = 0;
104 while ((numBits < 32) && (maxElem >> numBits))
105 numBits++;
106
107 if (numBits >= 32)
108 return false;
109
110 Byte numBitsByte = (Byte)numBits;
111
112 // use the upper 2 bits to encode the type used for numElem: byte, ushort, or uint
113 int n = NumBytesUInt(numElem);
114 int bits67 = (n == 4) ? 0 : 3 - n;
115 numBitsByte |= bits67 << 6;
116
117 numBitsByte |= (1 << 5); // bit 5 = 1 means lut mode
118
119 **ppByte = numBitsByte;
120 (*ppByte)++;
121
122 if (!EncodeUInt(ppByte, numElem, n)) // numElements = numIndexes to lut
123 return false;
124
125 unsigned int nLut = (unsigned int)m_tmpLutVec.size();
126 if (nLut < 1 || nLut >= 255)
127 return false;
128
129 **ppByte = (Byte)nLut + 1; // size of lut, incl the 0
130 (*ppByte)++;
131
132 BitStuff(ppByte, m_tmpLutVec, numBits); // lut
133
134 int nBitsLut = 0;
135 while (nLut >> nBitsLut) // indexes are in [0 .. nLut]
136 nBitsLut++;
137
138 BitStuff(ppByte, m_tmpIndexVec, nBitsLut); // indexes
139
140 return true;
141 }
142
143 // -------------------------------------------------------------------------- ;
144
145 // if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
146
Decode(const Byte ** ppByte,vector<unsigned int> & dataVec,int lerc2Version) const147 bool BitStuffer2::Decode(const Byte** ppByte, vector<unsigned int>& dataVec, int lerc2Version) const
148 {
149 if (!ppByte)
150 return false;
151
152 Byte numBitsByte = **ppByte;
153 (*ppByte)++;
154
155 int bits67 = numBitsByte >> 6;
156 int nb = (bits67 == 0) ? 4 : 3 - bits67;
157
158 bool doLut = (numBitsByte & (1 << 5)) ? true : false; // bit 5
159 numBitsByte &= 31; // bits 0-4;
160 int numBits = numBitsByte;
161
162 unsigned int numElements = 0;
163 if (!DecodeUInt(ppByte, numElements, nb))
164 return false;
165
166 if (!doLut)
167 {
168 if (numBits > 0) // numBits can be 0
169 {
170 if (lerc2Version >= 3)
171 BitUnStuff(ppByte, dataVec, numElements, numBits);
172 else
173 BitUnStuff_Before_Lerc2v3(ppByte, dataVec, numElements, numBits);
174 }
175 else // numBits = 0, all elements = 0
176 {
177 dataVec.resize(numElements);
178 memset(&dataVec[0], 0, numElements * sizeof(unsigned int));
179 }
180 }
181 else
182 {
183 Byte nLutByte = **ppByte;
184 (*ppByte)++;
185
186 int nLut = nLutByte - 1;
187
188 // unstuff lut w/o the 0
189 if (lerc2Version >= 3)
190 BitUnStuff(ppByte, m_tmpLutVec, nLut, numBits);
191 else
192 BitUnStuff_Before_Lerc2v3(ppByte, m_tmpLutVec, nLut, numBits);
193
194 int nBitsLut = 0;
195 while (nLut >> nBitsLut)
196 nBitsLut++;
197
198 // unstuff indexes
199 if (lerc2Version >= 3)
200 BitUnStuff(ppByte, dataVec, numElements, nBitsLut);
201 else
202 BitUnStuff_Before_Lerc2v3(ppByte, dataVec, numElements, nBitsLut);
203
204 // replace indexes by values
205 m_tmpLutVec.insert(m_tmpLutVec.begin(), 0); // put back in the 0
206 for (unsigned int i = 0; i < numElements; i++)
207 dataVec[i] = m_tmpLutVec[dataVec[i]];
208 }
209
210 return true;
211 }
212
213 // -------------------------------------------------------------------------- ;
214
ComputeNumBytesNeededLut(const vector<pair<unsigned int,unsigned int>> & sortedDataVec,bool & doLut)215 unsigned int BitStuffer2::ComputeNumBytesNeededLut(const vector<pair<unsigned int, unsigned int> >& sortedDataVec, bool& doLut)
216 {
217 unsigned int maxElem = sortedDataVec.back().first;
218 unsigned int numElem = (unsigned int)sortedDataVec.size();
219
220 int numBits = 0;
221 while ((numBits < 32) && (maxElem >> numBits))
222 numBits++;
223 unsigned int numBytes = 1 + NumBytesUInt(numElem) + ((numElem * numBits + 7) >> 3);
224
225 // go through and count how often the value changes
226 int nLut = 0;
227 for (unsigned int i = 1; i < numElem; i++)
228 if (sortedDataVec[i].first != sortedDataVec[i - 1].first)
229 nLut++;
230
231 int nBitsLut = 0;
232 while (nLut >> nBitsLut)
233 nBitsLut++;
234
235 unsigned int numBitsTotalLut = nLut * numBits; // num bits w/o the 0
236 unsigned int numBytesLut = 1 + NumBytesUInt(numElem) + 1 + ((numBitsTotalLut + 7) >> 3) + ((numElem * nBitsLut + 7) >> 3);
237
238 doLut = numBytesLut < numBytes;
239 return min(numBytesLut, numBytes);
240 }
241
242 // -------------------------------------------------------------------------- ;
243 // -------------------------------------------------------------------------- ;
244
BitUnStuff_Before_Lerc2v3(const Byte ** ppByte,vector<unsigned int> & dataVec,unsigned int numElements,int numBits) const245 void BitStuffer2::BitUnStuff_Before_Lerc2v3(const Byte** ppByte, vector<unsigned int>& dataVec,
246 unsigned int numElements, int numBits) const
247 {
248 dataVec.resize(numElements, 0); // init with 0
249
250 unsigned int numUInts = (numElements * numBits + 31) / 32;
251 unsigned int numBytes = numUInts * sizeof(unsigned int);
252 #pragma GCC diagnostic push
253 #pragma GCC diagnostic ignored "-Wcast-qual"
254 #pragma GCC diagnostic ignored "-Wcast-align"
255 unsigned int* arr = (unsigned int*)(*ppByte);
256 #pragma GCC diagnostic pop
257
258 unsigned int* srcPtr = arr;
259 srcPtr += numUInts;
260
261 // needed to save the 0-3 bytes not used in the last UInt
262 srcPtr--;
263 unsigned int lastUInt = *srcPtr;
264 unsigned int numBytesNotNeeded = NumTailBytesNotNeeded(numElements, numBits);
265 unsigned int n = numBytesNotNeeded;
266
267 while (n--)
268 {
269 unsigned int val;
270 memcpy(&val, srcPtr, sizeof(unsigned int));
271 val <<= 8;
272 memcpy(srcPtr, &val, sizeof(unsigned int));
273 }
274
275 // do the un-stuffing
276 srcPtr = arr;
277 unsigned int* dstPtr = &dataVec[0];
278 int bitPos = 0;
279
280 for (unsigned int i = 0; i < numElements; i++)
281 {
282 if (32 - bitPos >= numBits)
283 {
284 unsigned int val;
285 memcpy(&val, srcPtr, sizeof(unsigned int));
286 unsigned int n = val << bitPos;
287
288 *dstPtr++ = n >> (32 - numBits);
289 bitPos += numBits;
290 if (bitPos == 32) // shift >= 32 is undefined
291 {
292 bitPos = 0;
293 srcPtr++;
294 }
295 }
296 else
297 {
298 unsigned int val;
299 memcpy(&val, srcPtr, sizeof(unsigned int));
300 srcPtr++;
301 unsigned int n = val << bitPos;
302 *dstPtr = n >> (32 - numBits);
303 bitPos -= (32 - numBits);
304 memcpy(&val, srcPtr, sizeof(unsigned int));
305 *dstPtr++ |= val >> (32 - bitPos);
306 }
307 }
308
309 if (numBytesNotNeeded > 0)
310 memcpy(srcPtr, &lastUInt, sizeof(unsigned int)); // restore the last UInt
311
312 *ppByte += numBytes - numBytesNotNeeded;
313 }
314
315 // -------------------------------------------------------------------------- ;
316
317 // starting with version Lerc2v3: integer >> into local uint buffer, plus final memcpy
318
BitStuff(Byte ** ppByte,const vector<unsigned int> & dataVec,int numBits) const319 void BitStuffer2::BitStuff(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits) const
320 {
321 unsigned int numElements = (unsigned int)dataVec.size();
322 unsigned int numUInts = (numElements * numBits + 31) / 32;
323 unsigned int numBytes = numUInts * sizeof(unsigned int);
324
325 m_tmpBitStuffVec.resize(numUInts);
326 unsigned int* dstPtr = &m_tmpBitStuffVec[0];
327
328 memset(dstPtr, 0, numBytes);
329
330 // do the stuffing
331 const unsigned int* srcPtr = &dataVec[0];
332 int bitPos = 0;
333
334 for (unsigned int i = 0; i < numElements; i++)
335 {
336 if (32 - bitPos >= numBits)
337 {
338 *dstPtr |= (*srcPtr++) << bitPos;
339 bitPos += numBits;
340 if (bitPos == 32) // shift >= 32 is undefined
341 {
342 dstPtr++;
343 bitPos = 0;
344 }
345 }
346 else
347 {
348 *dstPtr++ |= (*srcPtr) << bitPos;
349 *dstPtr |= (*srcPtr++) >> (32 - bitPos);
350 bitPos += numBits - 32;
351 }
352 }
353
354 // copy the bytes to the outgoing byte stream
355 int numBytesUsed = numBytes - NumTailBytesNotNeeded(numElements, numBits);
356 memcpy(*ppByte, &m_tmpBitStuffVec[0], numBytesUsed);
357
358 *ppByte += numBytesUsed;
359 }
360
361 // -------------------------------------------------------------------------- ;
362
BitUnStuff(const Byte ** ppByte,vector<unsigned int> & dataVec,unsigned int numElements,int numBits) const363 void BitStuffer2::BitUnStuff(const Byte** ppByte, vector<unsigned int>& dataVec,
364 unsigned int numElements, int numBits) const
365 {
366 dataVec.resize(numElements);
367
368 unsigned int numUInts = (numElements * numBits + 31) / 32;
369 unsigned int numBytes = numUInts * sizeof(unsigned int);
370
371 m_tmpBitStuffVec.resize(numUInts);
372 m_tmpBitStuffVec[numUInts - 1] = 0; // set last uint to 0
373
374 // copy the bytes from the incoming byte stream
375 int numBytesUsed = numBytes - NumTailBytesNotNeeded(numElements, numBits);
376 memcpy(&m_tmpBitStuffVec[0], *ppByte, numBytesUsed);
377
378 // do the un-stuffing
379 unsigned int* srcPtr = &m_tmpBitStuffVec[0];
380 unsigned int* dstPtr = &dataVec[0];
381 int bitPos = 0;
382 int nb = 32 - numBits;
383
384 for (unsigned int i = 0; i < numElements; i++)
385 {
386 if (nb - bitPos >= 0)
387 {
388 *dstPtr++ = ((*srcPtr) << (nb - bitPos)) >> nb;
389 bitPos += numBits;
390 if (bitPos == 32) // shift >= 32 is undefined
391 {
392 srcPtr++;
393 bitPos = 0;
394 }
395 }
396 else
397 {
398 *dstPtr = (*srcPtr++) >> bitPos;
399 *dstPtr++ |= ((*srcPtr) << (64 - numBits - bitPos)) >> nb;
400 bitPos -= nb;
401 }
402 }
403
404 *ppByte += numBytesUsed;
405 }
406
407 // -------------------------------------------------------------------------- ;
408
409