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