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