Line data Source code
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 : Lucian Plesea (provided checksum code)
23 : */
24 :
25 : #include "Defines.h"
26 : #include "Lerc2.h"
27 :
28 : #include <climits>
29 : #include <cstdint>
30 :
31 : USING_NAMESPACE_LERC
32 : using namespace std;
33 :
34 0 : static void ignore_ret_val(bool) {}
35 :
36 : // -------------------------------------------------------------------------- ;
37 :
38 7816 : Lerc2::Lerc2()
39 : {
40 7811 : Init();
41 7814 : }
42 :
43 : // -------------------------------------------------------------------------- ;
44 :
45 0 : Lerc2::Lerc2(int nDim, int nCols, int nRows, const Byte* pMaskBits)
46 : {
47 0 : Init();
48 0 : ignore_ret_val(Set(nDim, nCols, nRows, pMaskBits));
49 0 : }
50 :
51 : // -------------------------------------------------------------------------- ;
52 :
53 5180 : bool Lerc2::SetEncoderToOldVersion(int version)
54 : {
55 5180 : if (version < 2 || version > kCurrVersion)
56 0 : return false;
57 :
58 5180 : if (version < 4 && m_headerInfo.nDim > 1)
59 0 : return false;
60 :
61 5180 : m_headerInfo.version = version;
62 :
63 5180 : return true;
64 : }
65 :
66 : // -------------------------------------------------------------------------- ;
67 :
68 7815 : void Lerc2::Init()
69 : {
70 7815 : m_microBlockSize = 8;
71 7815 : m_maxValToQuantize = 0;
72 7815 : m_encodeMask = true;
73 7815 : m_writeDataOneSweep = false;
74 7815 : m_imageEncodeMode = IEM_Tiling;
75 :
76 7815 : m_headerInfo.RawInit();
77 7814 : m_headerInfo.version = kCurrVersion;
78 7814 : m_headerInfo.microBlockSize = m_microBlockSize;
79 7814 : }
80 :
81 : // -------------------------------------------------------------------------- ;
82 :
83 5181 : bool Lerc2::Set(int nDim, int nCols, int nRows, const Byte* pMaskBits)
84 : {
85 5181 : if (nDim > 1 && m_headerInfo.version < 4)
86 0 : return false;
87 :
88 5181 : if (!m_bitMask.SetSize(nCols, nRows))
89 0 : return false;
90 :
91 5181 : if (pMaskBits)
92 : {
93 18 : memcpy(m_bitMask.Bits(), pMaskBits, m_bitMask.Size());
94 18 : m_headerInfo.numValidPixel = m_bitMask.CountValidBits();
95 : }
96 : else
97 : {
98 5163 : m_headerInfo.numValidPixel = nCols * nRows;
99 5163 : m_bitMask.SetAllValid();
100 : }
101 :
102 5181 : m_headerInfo.nDim = nDim;
103 5181 : m_headerInfo.nCols = nCols;
104 5181 : m_headerInfo.nRows = nRows;
105 :
106 5181 : return true;
107 : }
108 :
109 : // -------------------------------------------------------------------------- ;
110 :
111 : //// if the Lerc2 header should ever shrink in size to less than below, then update it (very unlikely)
112 : //
113 : //unsigned int Lerc2::MinNumBytesNeededToReadHeader()
114 : //{
115 : // unsigned int numBytes = (unsigned int)FileKey().length();
116 : // numBytes += 7 * sizeof(int);
117 : // numBytes += 3 * sizeof(double);
118 : // return numBytes;
119 : //}
120 :
121 : // -------------------------------------------------------------------------- ;
122 :
123 7314 : bool Lerc2::GetHeaderInfo(const Byte* pByte, size_t nBytesRemaining, struct HeaderInfo& hd)
124 : {
125 7314 : if (!pByte || !IsLittleEndianSystem())
126 0 : return false;
127 :
128 7315 : return ReadHeader(&pByte, nBytesRemaining, hd);
129 : }
130 :
131 : // -------------------------------------------------------------------------- ;
132 : // -------------------------------------------------------------------------- ;
133 :
134 5181 : unsigned int Lerc2::ComputeNumBytesHeaderToWrite(const struct HeaderInfo& hd)
135 : {
136 5181 : unsigned int numBytes = (unsigned int)FileKey().length();
137 5181 : numBytes += 1 * sizeof(int);
138 5181 : numBytes += (hd.version >= 3 ? 1 : 0) * sizeof(unsigned int);
139 5181 : numBytes += (hd.version >= 4 ? 7 : 6) * sizeof(int);
140 5181 : numBytes += 3 * sizeof(double);
141 5181 : return numBytes;
142 : }
143 :
144 : // -------------------------------------------------------------------------- ;
145 :
146 5181 : bool Lerc2::WriteHeader(Byte** ppByte, const struct HeaderInfo& hd)
147 : {
148 5181 : if (!ppByte)
149 0 : return false;
150 :
151 5181 : Byte* ptr = *ppByte;
152 :
153 10362 : string fileKey = FileKey();
154 5181 : size_t len = fileKey.length();
155 5181 : memcpy(ptr, fileKey.c_str(), len);
156 5181 : ptr += len;
157 :
158 5181 : memcpy(ptr, &hd.version, sizeof(int));
159 5181 : ptr += sizeof(int);
160 :
161 5181 : if (hd.version >= 3)
162 : {
163 370 : unsigned int checksum = 0;
164 370 : memcpy(ptr, &checksum, sizeof(unsigned int)); // place holder to be filled by the real check sum later
165 370 : ptr += sizeof(unsigned int);
166 : }
167 :
168 10362 : vector<int> intVec;
169 5181 : intVec.push_back(hd.nRows);
170 5181 : intVec.push_back(hd.nCols);
171 :
172 5181 : if (hd.version >= 4)
173 : {
174 370 : intVec.push_back(hd.nDim);
175 : }
176 :
177 5181 : intVec.push_back(hd.numValidPixel);
178 5181 : intVec.push_back(hd.microBlockSize);
179 5181 : intVec.push_back(hd.blobSize);
180 5181 : intVec.push_back((int)hd.dt);
181 :
182 5181 : len = intVec.size() * sizeof(int);
183 5181 : memcpy(ptr, &intVec[0], len);
184 5181 : ptr += len;
185 :
186 5181 : vector<double> dblVec;
187 5181 : dblVec.push_back(hd.maxZError);
188 5181 : dblVec.push_back(hd.zMin);
189 5181 : dblVec.push_back(hd.zMax);
190 :
191 5181 : len = dblVec.size() * sizeof(double);
192 5181 : memcpy(ptr, &dblVec[0], len);
193 5181 : ptr += len;
194 :
195 5181 : *ppByte = ptr;
196 5181 : return true;
197 : }
198 :
199 : // -------------------------------------------------------------------------- ;
200 :
201 9948 : bool Lerc2::ReadHeader(const Byte** ppByte, size_t& nBytesRemainingInOut, struct HeaderInfo& hd)
202 : {
203 9948 : if (!ppByte || !*ppByte)
204 9 : return false;
205 :
206 9939 : const Byte* ptr = *ppByte;
207 9939 : size_t nBytesRemaining = nBytesRemainingInOut;
208 :
209 19878 : string fileKey = FileKey();
210 9950 : size_t keyLen = fileKey.length();
211 :
212 9945 : hd.RawInit();
213 :
214 9944 : if (nBytesRemaining < keyLen || memcmp(ptr, fileKey.c_str(), keyLen))
215 1022 : return false;
216 :
217 8926 : ptr += keyLen;
218 8926 : nBytesRemaining -= keyLen;
219 :
220 8926 : if (nBytesRemaining < sizeof(int) || !memcpy(&(hd.version), ptr, sizeof(int)))
221 0 : return false;
222 :
223 8926 : ptr += sizeof(int);
224 8926 : nBytesRemaining -= sizeof(int);
225 :
226 8926 : if (hd.version > kCurrVersion) // this reader is outdated
227 0 : return false;
228 :
229 8926 : if (hd.version >= 3)
230 : {
231 4084 : if (nBytesRemaining < sizeof(unsigned int) || !memcpy(&(hd.checksum), ptr, sizeof(unsigned int)))
232 0 : return false;
233 :
234 4084 : ptr += sizeof(unsigned int);
235 4084 : nBytesRemaining -= sizeof(unsigned int);
236 : }
237 :
238 8926 : int nInts = (hd.version >= 4) ? 7 : 6;
239 17843 : vector<int> intVec(nInts, 0);
240 17850 : vector<double> dblVec(3, 0);
241 :
242 8920 : size_t len = sizeof(int) * intVec.size();
243 :
244 8934 : if (nBytesRemaining < len || !memcpy(&intVec[0], ptr, len))
245 0 : return false;
246 :
247 8929 : ptr += len;
248 8929 : nBytesRemaining -= len;
249 :
250 8929 : len = sizeof(double) * dblVec.size();
251 :
252 8924 : if (nBytesRemaining < len || !memcpy(&dblVec[0], ptr, len))
253 0 : return false;
254 :
255 8922 : ptr += len;
256 8922 : nBytesRemaining -= len;
257 :
258 8922 : int i = 0;
259 8922 : hd.nRows = intVec[i++];
260 8925 : hd.nCols = intVec[i++];
261 8926 : hd.nDim = (hd.version >= 4) ? intVec[i++] : 1;
262 8927 : hd.numValidPixel = intVec[i++];
263 8929 : hd.microBlockSize = intVec[i++];
264 8926 : hd.blobSize = intVec[i++];
265 8927 : const int dt = intVec[i++];
266 8925 : if (hd.nRows <= 0 || hd.nCols <= 0 || hd.nDim <= 0 || hd.numValidPixel < 0
267 8927 : || hd.microBlockSize <= 0 || hd.blobSize <= 0 || dt < DT_Char || dt > DT_Double)
268 0 : return false;
269 8925 : hd.dt = static_cast<DataType>(dt);
270 :
271 8925 : hd.maxZError = dblVec[0];
272 8926 : hd.zMin = dblVec[1];
273 8926 : hd.zMax = dblVec[2];
274 :
275 8927 : const uint64_t numPixel = (uint64_t)hd.nRows * hd.nCols;
276 8927 : if (numPixel > (uint64_t)INT_MAX || (uint64_t)hd.numValidPixel > numPixel)
277 0 : return false;
278 :
279 8927 : *ppByte = ptr;
280 8927 : nBytesRemainingInOut = nBytesRemaining;
281 :
282 8927 : return true;
283 : }
284 :
285 : // -------------------------------------------------------------------------- ;
286 :
287 5181 : bool Lerc2::WriteMask(Byte** ppByte) const
288 : {
289 5181 : if (!ppByte)
290 0 : return false;
291 :
292 5181 : int numValid = m_headerInfo.numValidPixel;
293 5181 : int numTotal = m_headerInfo.nCols * m_headerInfo.nRows;
294 :
295 5181 : bool needMask = numValid > 0 && numValid < numTotal;
296 :
297 5181 : Byte* ptr = *ppByte;
298 :
299 5181 : if (needMask && m_encodeMask)
300 : {
301 : Byte* pArrRLE;
302 : size_t numBytesRLE;
303 9 : RLE rle;
304 9 : if (!rle.compress((const Byte*)m_bitMask.Bits(), m_bitMask.Size(), &pArrRLE, numBytesRLE, false))
305 0 : return false;
306 :
307 9 : int numBytesMask = (int)numBytesRLE;
308 9 : memcpy(ptr, &numBytesMask, sizeof(int)); // num bytes for compressed mask
309 9 : ptr += sizeof(int);
310 9 : memcpy(ptr, pArrRLE, numBytesRLE);
311 9 : ptr += numBytesRLE;
312 :
313 18 : delete[] pArrRLE;
314 : }
315 : else
316 : {
317 5172 : memset(ptr, 0, sizeof(int)); // indicates no mask stored
318 5172 : ptr += sizeof(int);
319 : }
320 :
321 5181 : *ppByte = ptr;
322 5181 : return true;
323 : }
324 :
325 : // -------------------------------------------------------------------------- ;
326 :
327 2636 : bool Lerc2::ReadMask(const Byte** ppByte, size_t& nBytesRemainingInOut)
328 : {
329 2636 : if (!ppByte)
330 0 : return false;
331 :
332 2636 : int numValid = m_headerInfo.numValidPixel;
333 2636 : int w = m_headerInfo.nCols;
334 2636 : int h = m_headerInfo.nRows;
335 :
336 2636 : const Byte* ptr = *ppByte;
337 2636 : size_t nBytesRemaining = nBytesRemainingInOut;
338 :
339 : int numBytesMask;
340 2636 : if (nBytesRemaining < sizeof(int) || !memcpy(&numBytesMask, ptr, sizeof(int)))
341 0 : return false;
342 :
343 2636 : ptr += sizeof(int);
344 2636 : nBytesRemaining -= sizeof(int);
345 :
346 2636 : if (numValid == 0 || numValid == w * h)
347 : {
348 2625 : if (numBytesMask != 0)
349 0 : return false;
350 : }
351 :
352 2636 : if (!m_bitMask.SetSize(w, h))
353 0 : return false;
354 :
355 2635 : if (numValid == 0)
356 9 : m_bitMask.SetAllInvalid();
357 2626 : else if (numValid == w * h)
358 2615 : m_bitMask.SetAllValid();
359 11 : else if (numBytesMask > 0) // read it in
360 : {
361 12 : if (nBytesRemaining < static_cast<size_t>(numBytesMask))
362 0 : return false;
363 :
364 12 : RLE rle;
365 12 : if (!rle.decompress(ptr, nBytesRemaining, m_bitMask.Bits(), m_bitMask.Size()))
366 0 : return false;
367 :
368 12 : ptr += numBytesMask;
369 12 : nBytesRemaining -= numBytesMask;
370 : }
371 : // else use previous mask
372 :
373 2635 : *ppByte = ptr;
374 2635 : nBytesRemainingInOut = nBytesRemaining;
375 :
376 2635 : return true;
377 : }
378 :
379 : // -------------------------------------------------------------------------- ;
380 :
381 5181 : bool Lerc2::DoChecksOnEncode(Byte* pBlobBegin, Byte* pBlobEnd) const
382 : {
383 5181 : if ((size_t)(pBlobEnd - pBlobBegin) != (size_t)m_headerInfo.blobSize)
384 0 : return false;
385 :
386 5181 : if (m_headerInfo.version >= 3)
387 : {
388 370 : int blobSize = (int)(pBlobEnd - pBlobBegin);
389 370 : int nBytes = (int)(FileKey().length() + sizeof(int) + sizeof(unsigned int)); // start right after the checksum entry
390 370 : if (blobSize < nBytes)
391 0 : return false;
392 370 : unsigned int checksum = ComputeChecksumFletcher32(pBlobBegin + nBytes, blobSize - nBytes);
393 :
394 370 : nBytes -= sizeof(unsigned int);
395 370 : memcpy(pBlobBegin + nBytes, &checksum, sizeof(unsigned int));
396 : }
397 :
398 5181 : return true;
399 : }
400 :
401 : // -------------------------------------------------------------------------- ;
402 :
403 : // from https://en.wikipedia.org/wiki/Fletcher's_checksum
404 : // modified from ushorts to bytes (by Lucian Plesea)
405 :
406 1393 : unsigned int Lerc2::ComputeChecksumFletcher32(const Byte* pByte, int len)
407 : {
408 1393 : unsigned int sum1 = 0xffff, sum2 = 0xffff;
409 1393 : unsigned int words = len / 2;
410 :
411 8830 : while (words)
412 : {
413 7437 : unsigned int tlen = (words >= 359) ? 359 : words;
414 7437 : words -= tlen;
415 2411450 : do {
416 2418890 : sum1 += (*pByte++ << 8);
417 2418890 : sum2 += sum1 += *pByte++;
418 2418890 : } while (--tlen);
419 :
420 7437 : sum1 = (sum1 & 0xffff) + (sum1 >> 16);
421 7437 : sum2 = (sum2 & 0xffff) + (sum2 >> 16);
422 : }
423 :
424 : // add the straggler byte if it exists
425 1393 : if (len & 1)
426 637 : sum2 += sum1 += (*pByte << 8);
427 :
428 : // second reduction step to reduce sums to 16 bits
429 1393 : sum1 = (sum1 & 0xffff) + (sum1 >> 16);
430 1393 : sum2 = (sum2 & 0xffff) + (sum2 >> 16);
431 :
432 1393 : return sum2 << 16 | sum1;
433 : }
434 :
435 : // -------------------------------------------------------------------------- ;
436 :
437 : //struct MyLessThanOp
438 : //{
439 : // inline bool operator() (const pair<unsigned int, unsigned int>& p0,
440 : // const pair<unsigned int, unsigned int>& p1) { return p0.first < p1.first; }
441 : //};
442 :
443 : // -------------------------------------------------------------------------- ;
444 :
445 709569 : void Lerc2::SortQuantArray(const vector<unsigned int>& quantVec, vector<pair<unsigned int, unsigned int> >& sortedQuantVec)
446 : {
447 709569 : int numElem = (int)quantVec.size();
448 709569 : sortedQuantVec.resize(numElem);
449 :
450 71881600 : for (int i = 0; i < numElem; i++)
451 71172000 : sortedQuantVec[i] = pair<unsigned int, unsigned int>(quantVec[i], i);
452 :
453 : //std::sort(sortedQuantVec.begin(), sortedQuantVec.end(), MyLessThanOp());
454 :
455 709569 : std::sort(sortedQuantVec.begin(), sortedQuantVec.end(),
456 371995000 : [](const pair<unsigned int, unsigned int>& p0,
457 371995000 : const pair<unsigned int, unsigned int>& p1) { return p0.first < p1.first; });
458 709569 : }
459 :
460 : // -------------------------------------------------------------------------- ;
461 :
|