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 LERC2_H
25 #define LERC2_H
26
27 #include <cfloat>
28 #include <cmath>
29 #include <algorithm>
30 #include <string>
31 #include "BitMask.h"
32 #include "BitStuffer2.h"
33
34 NAMESPACE_LERC_START
35
36 /** Lerc2 v1
37 *
38 * -- allow for lossless compression of all common data types
39 * -- avoid data type conversions and copies
40 * -- optimized compression for segmented rasters (10-15x lossless)
41 * -- micro block is 8x8 fixed, only gets doubled to 16x16 if bit rate < 1 bpp
42 * -- cnt is replaced by bit mask
43 * -- Lerc blob header has data range [min, max]
44 * -- harden consistency checks to detect if the byte blob has been tampered with
45 * -- drop support for big endian, this is legacy now
46 *
47 * Lerc2 v2
48 *
49 * -- add Huffman coding for better lossless compression of 8 bit data types Char, Byte
50 *
51 * Lerc2 v3
52 *
53 * -- add checksum for the entire byte blob, for more rigorous detection of compressed data corruption
54 * -- for the main bit stuffing routine, use an extra uint buffer for guaranteed memory alignment
55 * -- this also allows to drop the NumExtraBytesToAllocate functions
56 *
57 * Lerc2 v4
58 *
59 * -- allow array per pixel, nDim values per pixel. Such as RGB, complex number, or larger arrays per pixel
60 * -- extend Huffman coding for 8 bit data types from delta only to trying both delta and orig
61 * -- for integer data types, allow to drop bit planes containing only random noise
62 *
63 * Lerc2 v5
64 * -- for float data (as it might be lower precision like %.2f), try raise maxZError if possible w/o extra loss
65 * -- add delta encoding of a block iDim relative to previous block (iDim - 1)
66 *
67 */
68
69 class Lerc2
70 {
71 public:
72 Lerc2();
73 Lerc2(int nDim, int nCols, int nRows, const Byte* pMaskBits = nullptr); // valid / invalid bits as byte array
~Lerc2()74 virtual ~Lerc2() {}
75
CurrentVersion()76 static int CurrentVersion() { return 5; }
77
78 bool SetEncoderToOldVersion(int version); // call this to encode compatible to an old decoder
79
80 bool Set(int nDim, int nCols, int nRows, const Byte* pMaskBits = nullptr);
81
82 template<class T>
83 unsigned int ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask);
84
85 /// dst buffer already allocated; byte ptr is moved like a file pointer
86 template<class T>
87 bool Encode(const T* arr, Byte** ppByte);
88
89 // data types supported by Lerc2
90 enum DataType {DT_Char = 0, DT_Byte, DT_Short, DT_UShort, DT_Int, DT_UInt, DT_Float, DT_Double, DT_Undefined};
91
92 struct HeaderInfo
93 {
94 int version;
95 unsigned int checksum;
96 int nRows,
97 nCols,
98 nDim,
99 numValidPixel,
100 microBlockSize,
101 blobSize;
102
103 DataType dt;
104
105 double maxZError,
106 zMin, // if nDim > 1, this is the overall range
107 zMax;
108
RawInitHeaderInfo109 void RawInit() { memset(this, 0, sizeof(struct HeaderInfo)); }
110
TryHuffmanHeaderInfo111 bool TryHuffman() const { return version > 1 && (dt == DT_Byte || dt == DT_Char) && maxZError == 0.5; }
112 };
113
114 static bool GetHeaderInfo(const Byte* pByte, size_t nBytesRemaining, struct HeaderInfo& headerInfo, bool& bHasMask);
115
116 /// dst buffer already allocated; byte ptr is moved like a file pointer
117 template<class T>
118 bool Decode(const Byte** ppByte, size_t& nBytesRemaining, T* arr, Byte* pMaskBits = nullptr); // if mask ptr is not 0, mask bits are returned (even if all valid or same as previous)
119
120 private:
121
122 enum ImageEncodeMode { IEM_Tiling = 0, IEM_DeltaHuffman, IEM_Huffman };
123 enum BlockEncodeMode { BEM_RawBinary = 0, BEM_BitStuffSimple, BEM_BitStuffLUT };
124
125 int m_microBlockSize,
126 m_maxValToQuantize;
127 BitMask m_bitMask;
128 HeaderInfo m_headerInfo;
129 BitStuffer2 m_bitStuffer2;
130 bool m_encodeMask,
131 m_writeDataOneSweep;
132 ImageEncodeMode m_imageEncodeMode;
133
134 std::vector<double> m_zMinVec, m_zMaxVec;
135 std::vector<std::pair<unsigned short, unsigned int> > m_huffmanCodes; // <= 256 codes, 1.5 kB
136
137 private:
FileKey()138 static std::string FileKey() { return "Lerc2 "; }
IsLittleEndianSystem()139 static bool IsLittleEndianSystem() { int n = 1; return (1 == *((Byte*)&n)) && (4 == sizeof(int)); }
140 void Init();
141
142 static unsigned int ComputeNumBytesHeaderToWrite(const struct HeaderInfo& hd);
143 static bool WriteHeader(Byte** ppByte, const struct HeaderInfo& hd);
144 static bool ReadHeader(const Byte** ppByte, size_t& nBytesRemaining, struct HeaderInfo& hd);
145
146 bool WriteMask(Byte** ppByte) const;
147 bool ReadMask(const Byte** ppByte, size_t& nBytesRemaining);
148
149 bool DoChecksOnEncode(Byte* pBlobBegin, Byte* pBlobEnd) const;
150 static unsigned int ComputeChecksumFletcher32(const Byte* pByte, int len);
151
152 static void AddUIntToCounts(int* pCounts, unsigned int val, int nBits);
153 static void AddIntToCounts(int* pCounts, int val, int nBits);
154
155 template<class T>
156 bool TryBitPlaneCompression(const T* data, double eps, double& newMaxZError) const;
157
158 template<class T>
159 bool TryRaiseMaxZError(const T* data, double& maxZError) const;
160
161 static bool PruneCandidates(std::vector<double>& roundErr, std::vector<double>& zErr,
162 std::vector<int>& zFac, double maxZError);
163
164 template<class T>
165 bool WriteDataOneSweep(const T* data, Byte** ppByte) const;
166
167 template<class T>
168 bool ReadDataOneSweep(const Byte** ppByte, size_t& nBytesRemaining, T* data) const;
169
170 template<class T>
171 bool ComputeMinMaxRanges(const T* data, std::vector<double>& zMinVec, std::vector<double>& zMaxVec) const;
172
173 template<class T>
174 bool WriteTiles(const T* data, Byte** ppByte, int& numBytes) const;
175
176 template<class T>
177 bool ReadTiles(const Byte** ppByte, size_t& nBytesRemaining, T* data) const;
178
179 template<class T>
180 bool GetValidDataAndStats(const T* data, int i0, int i1, int j0, int j1, int iDim,
181 T* dataBuf, T& zMin, T& zMax, int& numValidPixel, bool& tryLut) const;
182
183 template<class T>
184 static bool ComputeDiffSliceInt(const T* data, const T* prevData, int numValidPixel, bool bCheckForIntOverflow,
185 double maxZError, std::vector<int>& diffDataVec, int& zMin, int& zMax, bool& tryLut);
186
187 template<class T>
188 static bool ComputeDiffSliceFlt(const T* data, const T* prevData, int numValidPixel, bool bCheckForFltRndErr,
189 double maxZError, std::vector<T>& diffDataVec, T& zMin, T& zMax, bool& tryLut);
190
191 static bool NeedToCheckForIntOverflow(const HeaderInfo& hd);
192 static bool NeedToCheckForFltRndErr(const HeaderInfo& hd);
193
194 static double ComputeMaxVal(double zMin, double zMax, double maxZError);
195
196 template<class T>
197 bool NeedToQuantize(int numValidPixel, T zMin, T zMax) const;
198
199 template<class T>
200 void Quantize(const T* dataBuf, int num, T zMin, std::vector<unsigned int>& quantVec) const;
201
202 template<class T>
203 static void ScaleBack(T* dataBuf, const std::vector<unsigned int>& quantVec,
204 double zMin, bool bDiff, bool bClamp, double zMaxClamp, double maxZError);
205
206 template<class T>
207 static void ScaleBackConstBlock(T* dataBuf, int num, double zMin, bool bClamp, double zMaxClamp);
208
209 template<class T>
210 int NumBytesTile(int numValidPixel, T zMin, T zMax, DataType dtZ, bool tryLut, BlockEncodeMode& blockEncodeMode,
211 const std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec) const;
212
213 template<class T>
214 bool WriteTile(const T* dataBuf, int num, Byte** ppByte, int& numBytesWritten, int j0, T zMin, T zMax,
215 DataType dtZ, bool bDiffEnc, const std::vector<unsigned int>& quantVec, BlockEncodeMode blockEncodeMode,
216 const std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec) const;
217
218 template<class T>
219 bool ReadTile(const Byte** ppByte, size_t& nBytesRemaining, T* data, int i0, int i1, int j0, int j1, int iDim,
220 std::vector<unsigned int>& bufferVec) const;
221
222 template<class T>
223 static int ReduceDataType(T z, DataType dt, DataType& dtReduced);
224
225 static DataType GetDataTypeUsed(DataType dt, int reducedTypeCode);
226
227 static DataType ValidateDataType(int dt);
228
229 static bool WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed);
230
231 static double ReadVariableDataType(const Byte** ppByte, DataType dtUsed);
232
233 template<class T>
234 static DataType GetDataType(T z);
235
236 static unsigned int GetMaxValToQuantize(DataType dt);
237
238 static unsigned int GetDataTypeSize(DataType dt);
239
240 static void SortQuantArray(const std::vector<unsigned int>& quantVec,
241 std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec);
242
243 template<class T>
244 void ComputeHuffmanCodes(const T* data, int& numBytes, ImageEncodeMode& imageEncodeMode,
245 std::vector<std::pair<unsigned short, unsigned int> >& codes) const;
246
247 template<class T>
248 void ComputeHistoForHuffman(const T* data, std::vector<int>& histo, std::vector<int>& deltaHisto) const;
249
250 template<class T>
251 bool EncodeHuffman(const T* data, Byte** ppByte) const;
252
253 template<class T>
254 bool DecodeHuffman(const Byte** ppByte, size_t& nBytesRemaining, T* data) const;
255
256 template<class T>
257 bool WriteMinMaxRanges(const T* data, Byte** ppByte) const;
258
259 template<class T>
260 bool ReadMinMaxRanges(const Byte** ppByte, size_t& nBytesRemaining, const T* data);
261
262 bool CheckMinMaxRanges(bool& minMaxEqual) const;
263
264 template<class T>
265 bool FillConstImage(T* data) const;
266 };
267
268 // -------------------------------------------------------------------------- ;
269 // -------------------------------------------------------------------------- ;
270
271 inline
AddUIntToCounts(int * pCounts,unsigned int val,int nBits)272 void Lerc2::AddUIntToCounts(int* pCounts, unsigned int val, int nBits)
273 {
274 pCounts[0] += val & 1;
275 for (int i = 1; i < nBits; i++)
276 pCounts[i] += (val >>= 1) & 1;
277 }
278
279 // -------------------------------------------------------------------------- ;
280
281 inline
AddIntToCounts(int * pCounts,int val,int nBits)282 void Lerc2::AddIntToCounts(int* pCounts, int val, int nBits)
283 {
284 pCounts[0] += val & 1;
285 for (int i = 1; i < nBits; i++)
286 pCounts[i] += (val >>= 1) & 1;
287 }
288
289 // -------------------------------------------------------------------------- ;
290
NeedToCheckForIntOverflow(const HeaderInfo & hd)291 inline bool Lerc2::NeedToCheckForIntOverflow(const HeaderInfo& hd)
292 {
293 return (hd.dt == DT_Int || hd.dt == DT_UInt) && (hd.zMax - hd.zMin >= 0x7FFFFFFF);
294 }
295
296 // -------------------------------------------------------------------------- ;
297
NeedToCheckForFltRndErr(const HeaderInfo & hd)298 inline bool Lerc2::NeedToCheckForFltRndErr(const HeaderInfo& hd)
299 {
300 if (hd.dt != DT_Float)
301 return false;
302
303 if (hd.zMax - hd.zMin > 100000) // prevent the below test falls through with extreme numbers like 10^38
304 return true;
305
306 float diff = (float)(hd.zMax - hd.zMin);
307 double testMax = (double)diff + hd.zMin;
308 double fltRndErr = fabs(testMax - hd.zMax);
309
310 return (fltRndErr > hd.maxZError / 8);
311 }
312
313 // -------------------------------------------------------------------------- ;
314
ComputeMaxVal(double zMin,double zMax,double maxZError)315 inline double Lerc2::ComputeMaxVal(double zMin, double zMax, double maxZError)
316 {
317 double fac = 1 / (2 * maxZError); // must match the code in Decode(), don't touch it
318 return (zMax - zMin) * fac;
319 }
320
321 // -------------------------------------------------------------------------- ;
322
323 template<class T>
NeedToQuantize(int numValidPixel,T zMin,T zMax)324 inline bool Lerc2::NeedToQuantize(int numValidPixel, T zMin, T zMax) const
325 {
326 if (numValidPixel == 0 || m_headerInfo.maxZError == 0)
327 return false;
328
329 double maxVal = ComputeMaxVal(zMin, zMax, m_headerInfo.maxZError);
330 return !(maxVal > m_maxValToQuantize || (unsigned int)(maxVal + 0.5) == 0);
331 }
332
333 // -------------------------------------------------------------------------- ;
334
335 template<class T>
Quantize(const T * dataBuf,int num,T zMin,std::vector<unsigned int> & quantVec)336 inline void Lerc2::Quantize(const T* dataBuf, int num, T zMin, std::vector<unsigned int>& quantVec) const
337 {
338 quantVec.resize(num);
339
340 if (m_headerInfo.dt < DT_Float && m_headerInfo.maxZError == 0.5) // int lossless
341 {
342 for (int i = 0; i < num; i++)
343 quantVec[i] = (unsigned int)(dataBuf[i] - zMin); // ok: char, short get promoted to int by C++ integral promotion rule
344 }
345 else // float and/or lossy
346 {
347 double scale = 1 / (2 * m_headerInfo.maxZError);
348 double zMinDbl = (double)zMin;
349
350 for (int i = 0; i < num; i++)
351 quantVec[i] = (unsigned int)(((double)dataBuf[i] - zMinDbl) * scale + 0.5); // ok, consistent with ComputeMaxVal(...)
352 //quantVec[i] = (unsigned int)((dataBuf[i] - zMin) * scale + 0.5); // bad, not consistent with ComputeMaxVal(...)
353 }
354 }
355
356 // -------------------------------------------------------------------------- ;
357
358 template<class T>
ScaleBack(T * dataBuf,const std::vector<unsigned int> & quantVec,double zMin,bool bDiff,bool bClamp,double zMaxClamp,double maxZError)359 inline void Lerc2::ScaleBack(T* dataBuf, const std::vector<unsigned int>& quantVec,
360 double zMin, bool bDiff, bool bClamp, double zMaxClamp, double maxZError)
361 {
362 double invScale = 2 * maxZError; // for int types this is int
363 int num = (int)quantVec.size();
364
365 if (!bClamp)
366 for (int i = 0; i < num; i++)
367 {
368 double z = zMin + quantVec[i] * invScale + (bDiff ? dataBuf[i] : 0);
369 dataBuf[i] = (T)z;
370 }
371 else
372 for (int i = 0; i < num; i++)
373 {
374 double z = zMin + quantVec[i] * invScale + (bDiff ? dataBuf[i] : 0);
375 dataBuf[i] = (T)std::min(z, zMaxClamp);
376 }
377 }
378
379 // -------------------------------------------------------------------------- ;
380
381 template<class T>
ScaleBackConstBlock(T * dataBuf,int num,double zMin,bool bClamp,double zMaxClamp)382 inline void Lerc2::ScaleBackConstBlock(T* dataBuf, int num, double zMin, bool bClamp, double zMaxClamp)
383 {
384 if (!bClamp)
385 for (int i = 0; i < num; i++)
386 dataBuf[i] = (T)(zMin + dataBuf[i]);
387 else
388 for (int i = 0; i < num; i++)
389 dataBuf[i] = (T)std::min(zMin + dataBuf[i], zMaxClamp);
390 }
391
392 // -------------------------------------------------------------------------- ;
393
394 template<class T>
NumBytesTile(int numValidPixel,T zMin,T zMax,DataType dtZ,bool tryLut,BlockEncodeMode & blockEncodeMode,const std::vector<std::pair<unsigned int,unsigned int>> & sortedQuantVec)395 inline int Lerc2::NumBytesTile(int numValidPixel, T zMin, T zMax, DataType dtZ, bool tryLut,
396 BlockEncodeMode& blockEncodeMode, const std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec) const
397 {
398 blockEncodeMode = BEM_RawBinary;
399
400 if (numValidPixel == 0 || (zMin == 0 && zMax == 0))
401 return 1;
402
403 double maxVal = 0, maxZError = m_headerInfo.maxZError;
404 int nBytesRaw = (int)(1 + numValidPixel * sizeof(T));
405
406 if ((maxZError == 0 && zMax > zMin)
407 || (maxZError > 0 && (maxVal = ComputeMaxVal(zMin, zMax, maxZError)) > m_maxValToQuantize))
408 {
409 return nBytesRaw;
410 }
411 else
412 {
413 DataType dtReduced;
414 ReduceDataType(zMin, dtZ, dtReduced);
415 int nBytes = 1 + GetDataTypeSize(dtReduced);
416
417 unsigned int maxElem = (unsigned int)(maxVal + 0.5);
418 if (maxElem > 0)
419 {
420 nBytes += (!tryLut) ? m_bitStuffer2.ComputeNumBytesNeededSimple(numValidPixel, maxElem)
421 : m_bitStuffer2.ComputeNumBytesNeededLut(sortedQuantVec, tryLut);
422 }
423
424 if (nBytes < nBytesRaw)
425 blockEncodeMode = (!tryLut || maxElem == 0) ? BEM_BitStuffSimple : BEM_BitStuffLUT;
426 else
427 nBytes = nBytesRaw;
428
429 return nBytes;
430 }
431 }
432
433 // -------------------------------------------------------------------------- ;
434
435 template<class T>
ReduceDataType(T z,DataType dt,DataType & dtReduced)436 inline int Lerc2::ReduceDataType(T z, DataType dt, DataType& dtReduced)
437 {
438 Byte b = (Byte)z;
439 switch (dt)
440 {
441 case DT_Short:
442 {
443 signed char c = (signed char)z;
444 int tc = (T)c == z ? 2 : (T)b == z ? 1 : 0;
445 dtReduced = (DataType)(dt - tc);
446 return tc;
447 }
448 case DT_UShort:
449 {
450 int tc = (T)b == z ? 1 : 0;
451 dtReduced = (DataType)(dt - 2 * tc);
452 return tc;
453 }
454 case DT_Int:
455 {
456 short s = (short)z;
457 unsigned short us = (unsigned short)z;
458 int tc = (T)b == z ? 3 : (T)s == z ? 2 : (T)us == z ? 1 : 0;
459 dtReduced = (DataType)(dt - tc);
460 return tc;
461 }
462 case DT_UInt:
463 {
464 unsigned short us = (unsigned short)z;
465 int tc = (T)b == z ? 2 : (T)us == z ? 1 : 0;
466 dtReduced = (DataType)(dt - 2 * tc);
467 return tc;
468 }
469 case DT_Float:
470 {
471 short s = (short)z;
472 int tc = (T)b == z ? 2 : (T)s == z ? 1 : 0;
473 dtReduced = tc == 0 ? dt : (tc == 1 ? DT_Short : DT_Byte);
474 return tc;
475 }
476 case DT_Double:
477 {
478 short s = (short)z;
479 int l = (int)z;
480 float f = (float)z;
481 int tc = (T)s == z ? 3 : (T)l == z ? 2 : (T)f == z ? 1 : 0;
482 dtReduced = tc == 0 ? dt : (DataType)(dt - 2 * tc + 1);
483 return tc;
484 }
485 default:
486 {
487 dtReduced = dt;
488 return 0;
489 }
490 }
491 }
492
493 // -------------------------------------------------------------------------- ;
494
ValidateDataType(int dt)495 inline Lerc2::DataType Lerc2::ValidateDataType(int dt)
496 {
497 if( dt >= DT_Char && dt <= DT_Double )
498 return static_cast<DataType>(dt);
499 return DT_Undefined;
500 }
501
502 // -------------------------------------------------------------------------- ;
503
504 inline
GetDataTypeUsed(DataType dt,int tc)505 Lerc2::DataType Lerc2::GetDataTypeUsed(DataType dt, int tc)
506 {
507 switch (dt)
508 {
509 case DT_Short:
510 case DT_Int: return ValidateDataType(dt - tc);
511 case DT_UShort:
512 case DT_UInt: return ValidateDataType(dt - 2 * tc);
513 case DT_Float: return tc == 0 ? dt : (tc == 1 ? DT_Short : DT_Byte);
514 case DT_Double: return tc == 0 ? dt : ValidateDataType(dt - 2 * tc + 1);
515 default:
516 return dt;
517 }
518 }
519
520 // -------------------------------------------------------------------------- ;
521
522 inline
WriteVariableDataType(Byte ** ppByte,double z,DataType dtUsed)523 bool Lerc2::WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed)
524 {
525 Byte* ptr = *ppByte;
526
527 switch (dtUsed)
528 {
529 case DT_Char:
530 {
531 *((signed char*)ptr) = (signed char)z;
532 ptr++;
533 break;
534 }
535 case DT_Byte:
536 {
537 *((Byte*)ptr) = (Byte)z;
538 ptr++;
539 break;
540 }
541 case DT_Short:
542 {
543 short s = (short)z;
544 memcpy(ptr, &s, sizeof(short));
545 ptr += 2;
546 break;
547 }
548 case DT_UShort:
549 {
550 unsigned short us = (unsigned short)z;
551 memcpy(ptr, &us, sizeof(unsigned short));
552 ptr += 2;
553 break;
554 }
555 case DT_Int:
556 {
557 int i = (int)z;
558 memcpy(ptr, &i, sizeof(int));
559 ptr += 4;
560 break;
561 }
562 case DT_UInt:
563 {
564 unsigned int n = (unsigned int)z;
565 memcpy(ptr, &n, sizeof(unsigned int));
566 ptr += 4;
567 break;
568 }
569 case DT_Float:
570 {
571 float f = (float)z;
572 memcpy(ptr, &f, sizeof(float));
573 ptr += 4;
574 break;
575 }
576 case DT_Double:
577 {
578 memcpy(ptr, &z, sizeof(double));
579 ptr += 8;
580 break;
581 }
582
583 default:
584 return false;
585 }
586
587 *ppByte = ptr;
588 return true;
589 }
590
591 // -------------------------------------------------------------------------- ;
592
593 inline
ReadVariableDataType(const Byte ** ppByte,DataType dtUsed)594 double Lerc2::ReadVariableDataType(const Byte** ppByte, DataType dtUsed)
595 {
596 const Byte* ptr = *ppByte;
597
598 switch (dtUsed)
599 {
600 case DT_Char:
601 {
602 signed char c = *((signed char*)ptr);
603 *ppByte = ptr + 1;
604 return c;
605 }
606 case DT_Byte:
607 {
608 Byte b = *((Byte*)ptr);
609 *ppByte = ptr + 1;
610 return b;
611 }
612 case DT_Short:
613 {
614 short s;
615 memcpy(&s, ptr, sizeof(short));
616 *ppByte = ptr + 2;
617 return s;
618 }
619 case DT_UShort:
620 {
621 unsigned short us;
622 memcpy(&us, ptr, sizeof(unsigned short));
623 *ppByte = ptr + 2;
624 return us;
625 }
626 case DT_Int:
627 {
628 int i;
629 memcpy(&i, ptr, sizeof(int));
630 *ppByte = ptr + 4;
631 return i;
632 }
633 case DT_UInt:
634 {
635 unsigned int n;
636 memcpy(&n, ptr, sizeof(unsigned int));
637 *ppByte = ptr + 4;
638 return n;
639 }
640 case DT_Float:
641 {
642 float f;
643 memcpy(&f, ptr, sizeof(float));
644 *ppByte = ptr + 4;
645 return f;
646 }
647 case DT_Double:
648 {
649 double d;
650 memcpy(&d, ptr, sizeof(double));
651 *ppByte = ptr + 8;
652 return d;
653 }
654 default:
655 return 0;
656 }
657 }
658
659 // -------------------------------------------------------------------------- ;
660
661 inline
GetMaxValToQuantize(DataType dt)662 unsigned int Lerc2::GetMaxValToQuantize(DataType dt)
663 {
664 switch (dt)
665 {
666 case DT_Char:
667 case DT_Byte: //return (1 << 7) - 1; // disabled: allow LUT mode for 8 bit segmented
668 case DT_Short:
669 case DT_UShort: return (1 << 15) - 1;
670
671 case DT_Int:
672 case DT_UInt:
673 case DT_Float:
674 case DT_Double: return (1 << 30) - 1;
675
676 default:
677 return 0;
678 }
679 }
680
681 // -------------------------------------------------------------------------- ;
682
683 inline
GetDataTypeSize(DataType dt)684 unsigned int Lerc2::GetDataTypeSize(DataType dt)
685 {
686 switch (dt)
687 {
688 case DT_Char:
689 case DT_Byte: return 1;
690 case DT_Short:
691 case DT_UShort: return 2;
692 case DT_Int:
693 case DT_UInt:
694 case DT_Float: return 4;
695 case DT_Double: return 8;
696
697 default:
698 return 0;
699 }
700 }
701
702 // -------------------------------------------------------------------------- ;
703
704 inline
CheckMinMaxRanges(bool & minMaxEqual)705 bool Lerc2::CheckMinMaxRanges(bool& minMaxEqual) const
706 {
707 int nDim = m_headerInfo.nDim;
708 if ((int)m_zMinVec.size() != nDim || (int)m_zMaxVec.size() != nDim)
709 return false;
710
711 minMaxEqual = (0 == memcmp(&m_zMinVec[0], &m_zMaxVec[0], nDim * sizeof(m_zMinVec[0])));
712 return true;
713 }
714
715 // -------------------------------------------------------------------------- ;
716
717 NAMESPACE_LERC_END
718 #endif
719