/src/gdal/third_party/LercLib/Lerc2.h
Line | Count | Source (jump to first uncovered line) |
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 <algorithm> |
28 | | #include <cfloat> |
29 | | #include <cmath> |
30 | | #include <limits> |
31 | | #include <string> |
32 | | #include <typeinfo> |
33 | | #include "Defines.h" |
34 | | #include "BitMask.h" |
35 | | #include "BitStuffer2.h" |
36 | | #include "Huffman.h" |
37 | | #include "RLE.h" |
38 | | |
39 | | NAMESPACE_LERC_START |
40 | | |
41 | | /** Lerc2 v1 |
42 | | * |
43 | | * -- allow for lossless compression of all common data types |
44 | | * -- avoid data type conversions and copies |
45 | | * -- optimized compression for segmented rasters (10-15x lossless) |
46 | | * -- micro block is 8x8 fixed, only gets doubled to 16x16 if bit rate < 1 bpp |
47 | | * -- cnt is replaced by bit mask |
48 | | * -- Lerc blob header has data range [min, max] |
49 | | * -- harden consistency checks to detect if the byte blob has been tampered with |
50 | | * -- drop support for big endian, this is legacy now |
51 | | * |
52 | | * Lerc2 v2 |
53 | | * |
54 | | * -- add Huffman coding for better lossless compression of 8 bit data types Char, Byte |
55 | | * |
56 | | * Lerc2 v3 |
57 | | * |
58 | | * -- add checksum for the entire byte blob, for more rigorous detection of compressed data corruption |
59 | | * -- for the main bit stuffing routine, use an extra uint buffer for guaranteed memory alignment |
60 | | * -- this also allows dropping the NumExtraBytesToAllocate functions |
61 | | * |
62 | | * Lerc2 v4 |
63 | | * |
64 | | * -- allow array per pixel, nDim values per pixel. Such as RGB, complex number, or larger arrays per pixel |
65 | | * -- extend Huffman coding for 8 bit data types from delta only to trying both delta and orig |
66 | | * -- for integer data types, allow to drop bit planes containing only random noise |
67 | | * |
68 | | */ |
69 | | |
70 | | class Lerc2 |
71 | | { |
72 | | public: |
73 | | Lerc2(); |
74 | | Lerc2(int nDim, int nCols, int nRows, const Byte* pMaskBits = nullptr); // valid / invalid bits as byte array |
75 | 0 | ~Lerc2() {} |
76 | | |
77 | | bool SetEncoderToOldVersion(int version); // call this to encode compatible to an old decoder |
78 | | |
79 | | bool Set(int nDim, int nCols, int nRows, const Byte* pMaskBits = nullptr); |
80 | | |
81 | | template<class T> |
82 | | unsigned int ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask); |
83 | | |
84 | | //static unsigned int MinNumBytesNeededToReadHeader(); |
85 | | |
86 | | /// dst buffer already allocated; byte ptr is moved like a file pointer |
87 | | template<class T> |
88 | | bool Encode(const T* arr, Byte** ppByte); |
89 | | |
90 | | // data types supported by Lerc2 |
91 | | enum DataType {DT_Char = 0, DT_Byte, DT_Short, DT_UShort, DT_Int, DT_UInt, DT_Float, DT_Double, DT_Undefined}; |
92 | | |
93 | | struct HeaderInfo |
94 | | { |
95 | | int version; |
96 | | unsigned int checksum; |
97 | | int nRows, |
98 | | nCols, |
99 | | nDim, |
100 | | numValidPixel, |
101 | | microBlockSize, |
102 | | blobSize; |
103 | | |
104 | | DataType dt; |
105 | | |
106 | | double maxZError, |
107 | | zMin, // if nDim > 1, this is the overall range |
108 | | zMax; |
109 | | |
110 | 0 | void RawInit() { memset(this, 0, sizeof(struct HeaderInfo)); } |
111 | | |
112 | 0 | bool TryHuffman() const { return version > 1 && (dt == DT_Byte || dt == DT_Char) && maxZError == 0.5; } |
113 | | }; |
114 | | |
115 | | static bool GetHeaderInfo(const Byte* pByte, size_t nBytesRemaining, struct HeaderInfo& headerInfo); |
116 | | |
117 | | /// dst buffer already allocated; byte ptr is moved like a file pointer |
118 | | template<class T> |
119 | | 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) |
120 | | |
121 | | private: |
122 | | static const int kCurrVersion = 4; // 2: added Huffman coding to 8 bit types DT_Char, DT_Byte; |
123 | | // 3: changed the bit stuffing to using a uint aligned buffer, |
124 | | // added Fletcher32 checksum |
125 | | // 4: allow nDim values per pixel |
126 | | |
127 | | enum ImageEncodeMode { IEM_Tiling = 0, IEM_DeltaHuffman, IEM_Huffman }; |
128 | | enum BlockEncodeMode { BEM_RawBinary = 0, BEM_BitStuffSimple, BEM_BitStuffLUT }; |
129 | | |
130 | | int m_microBlockSize, |
131 | | m_maxValToQuantize; |
132 | | BitMask m_bitMask; |
133 | | HeaderInfo m_headerInfo; |
134 | | BitStuffer2 m_bitStuffer2; |
135 | | bool m_encodeMask, |
136 | | m_writeDataOneSweep; |
137 | | ImageEncodeMode m_imageEncodeMode; |
138 | | |
139 | | std::vector<double> m_zMinVec, m_zMaxVec; |
140 | | std::vector<std::pair<unsigned short, unsigned int> > m_huffmanCodes; // <= 256 codes, 1.5 kB |
141 | | |
142 | | private: |
143 | 0 | static std::string FileKey() { return "Lerc2 "; } |
144 | 0 | static bool IsLittleEndianSystem() { int n = 1; return (1 == *((Byte*)&n)) && (4 == sizeof(int)); } |
145 | | void Init(); |
146 | | |
147 | | static unsigned int ComputeNumBytesHeaderToWrite(const struct HeaderInfo& hd); |
148 | | static bool WriteHeader(Byte** ppByte, const struct HeaderInfo& hd); |
149 | | static bool ReadHeader(const Byte** ppByte, size_t& nBytesRemaining, struct HeaderInfo& hd); |
150 | | |
151 | | bool WriteMask(Byte** ppByte) const; |
152 | | bool ReadMask(const Byte** ppByte, size_t& nBytesRemaining); |
153 | | |
154 | | bool DoChecksOnEncode(Byte* pBlobBegin, Byte* pBlobEnd) const; |
155 | | static unsigned int ComputeChecksumFletcher32(const Byte* pByte, int len); |
156 | | |
157 | | static void AddUIntToCounts(int* pCounts, unsigned int val, int nBits); |
158 | | static void AddIntToCounts(int* pCounts, int val, int nBits); |
159 | | |
160 | | template<class T> |
161 | | bool TryBitPlaneCompression(const T* data, double eps, double& newMaxZError) const; |
162 | | |
163 | | template<class T> |
164 | | bool WriteDataOneSweep(const T* data, Byte** ppByte) const; |
165 | | |
166 | | template<class T> |
167 | | bool ReadDataOneSweep(const Byte** ppByte, size_t& nBytesRemaining, T* data) const; |
168 | | |
169 | | template<class T> |
170 | | bool WriteTiles(const T* data, Byte** ppByte, int& numBytes, std::vector<double>& zMinVec, std::vector<double>& zMaxVec) const; |
171 | | |
172 | | template<class T> |
173 | | bool ReadTiles(const Byte** ppByte, size_t& nBytesRemaining, T* data) const; |
174 | | |
175 | | template<class T> |
176 | | bool GetValidDataAndStats(const T* data, int i0, int i1, int j0, int j1, int iDim, |
177 | | T* dataBuf, T& zMinA, T& zMaxA, int& numValidPixel, bool& tryLutA) const; |
178 | | |
179 | | static double ComputeMaxVal(double zMin, double zMax, double maxZError); |
180 | | |
181 | | template<class T> |
182 | | bool NeedToQuantize(int numValidPixel, T zMin, T zMax) const; |
183 | | |
184 | | template<class T> |
185 | | bool Quantize(const T* dataBuf, int num, T zMin, std::vector<unsigned int>& quantVec) const; |
186 | | |
187 | | template<class T> |
188 | | int NumBytesTile(int numValidPixel, T zMin, T zMax, bool tryLut, BlockEncodeMode& blockEncodeMode, |
189 | | const std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec) const; |
190 | | |
191 | | template<class T> |
192 | | bool WriteTile(const T* dataBuf, int num, Byte** ppByte, int& numBytesWritten, int j0, T zMin, T zMax, |
193 | | const std::vector<unsigned int>& quantVec, BlockEncodeMode blockEncodeMode, |
194 | | const std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec) const; |
195 | | |
196 | | template<class T> |
197 | | bool ReadTile(const Byte** ppByte, size_t& nBytesRemaining, T* data, int i0, int i1, int j0, int j1, int iDim, |
198 | | std::vector<unsigned int>& bufferVec) const; |
199 | | |
200 | | template<class T> |
201 | | int TypeCode(T z, DataType& dtUsed) const; |
202 | | |
203 | | DataType GetDataTypeUsed(int typeCode) const; |
204 | | |
205 | | static DataType ValidateDataType(int dt); |
206 | | |
207 | | static bool WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed); |
208 | | |
209 | | static double ReadVariableDataType(const Byte** ppByte, DataType dtUsed); |
210 | | |
211 | | template<class T> DataType GetDataType(T z) const; |
212 | | |
213 | | static unsigned int GetMaxValToQuantize(DataType dt); |
214 | | |
215 | | static unsigned int GetDataTypeSize(DataType dt); |
216 | | |
217 | | static void SortQuantArray(const std::vector<unsigned int>& quantVec, |
218 | | std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec); |
219 | | |
220 | | template<class T> |
221 | | void ComputeHuffmanCodes(const T* data, int& numBytes, ImageEncodeMode& imageEncodeMode, |
222 | | std::vector<std::pair<unsigned short, unsigned int> >& codes) const; |
223 | | |
224 | | template<class T> |
225 | | void ComputeHistoForHuffman(const T* data, std::vector<int>& histo, std::vector<int>& deltaHisto) const; |
226 | | |
227 | | template<class T> |
228 | | bool EncodeHuffman(const T* data, Byte** ppByte) const; |
229 | | |
230 | | template<class T> |
231 | | bool DecodeHuffman(const Byte** ppByte, size_t& nBytesRemaining, T* data) const; |
232 | | |
233 | | template<class T> |
234 | | bool WriteMinMaxRanges(const T* data, Byte** ppByte) const; |
235 | | |
236 | | template<class T> |
237 | | bool ReadMinMaxRanges(const Byte** ppByte, size_t& nBytesRemaining, const T* data); |
238 | | |
239 | | bool CheckMinMaxRanges(bool& minMaxEqual) const; |
240 | | |
241 | | template<class T> |
242 | | bool FillConstImage(T* data) const; |
243 | | }; |
244 | | |
245 | | // -------------------------------------------------------------------------- ; |
246 | | // -------------------------------------------------------------------------- ; |
247 | | |
248 | | template<class T> |
249 | | unsigned int Lerc2::ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask) |
250 | 0 | { |
251 | 0 | if (!arr || !IsLittleEndianSystem()) |
252 | 0 | return 0; |
253 | | |
254 | | // header |
255 | 0 | unsigned int nBytesHeaderMask = ComputeNumBytesHeaderToWrite(m_headerInfo); |
256 | | |
257 | | // valid / invalid mask |
258 | 0 | int numValid = m_headerInfo.numValidPixel; |
259 | 0 | int numTotal = m_headerInfo.nCols * m_headerInfo.nRows; |
260 | |
|
261 | 0 | bool needMask = numValid > 0 && numValid < numTotal; |
262 | |
|
263 | 0 | m_encodeMask = encodeMask; |
264 | |
|
265 | 0 | nBytesHeaderMask += 1 * sizeof(int); // the mask encode numBytes |
266 | |
|
267 | 0 | if (needMask && encodeMask) |
268 | 0 | { |
269 | 0 | RLE rle; |
270 | 0 | size_t n = rle.computeNumBytesRLE((const Byte*)m_bitMask.Bits(), m_bitMask.Size()); |
271 | 0 | nBytesHeaderMask += (unsigned int)n; |
272 | 0 | } |
273 | |
|
274 | 0 | m_headerInfo.dt = GetDataType(arr[0]); |
275 | |
|
276 | 0 | if (m_headerInfo.dt == DT_Undefined) |
277 | 0 | return 0; |
278 | | |
279 | 0 | if (maxZError == 777) // cheat code |
280 | 0 | maxZError = -0.01; |
281 | |
|
282 | 0 | if (m_headerInfo.dt < DT_Float) // integer types |
283 | 0 | { |
284 | | // interpret a negative maxZError as bit plane epsilon; dflt = 0.01; |
285 | 0 | if (maxZError < 0 && (!TryBitPlaneCompression(arr, -maxZError, maxZError))) |
286 | 0 | maxZError = 0; |
287 | |
|
288 | 0 | maxZError = std::max(0.5, floor(maxZError)); |
289 | 0 | } |
290 | 0 | else if (maxZError < 0) // don't allow bit plane compression for float or double yet |
291 | 0 | return 0; |
292 | | |
293 | 0 | m_headerInfo.maxZError = maxZError; |
294 | 0 | m_headerInfo.zMin = 0; |
295 | 0 | m_headerInfo.zMax = 0; |
296 | 0 | m_headerInfo.microBlockSize = m_microBlockSize; |
297 | 0 | m_headerInfo.blobSize = nBytesHeaderMask; |
298 | |
|
299 | 0 | if (numValid == 0) |
300 | 0 | return nBytesHeaderMask; |
301 | | |
302 | 0 | m_maxValToQuantize = GetMaxValToQuantize(m_headerInfo.dt); |
303 | |
|
304 | 0 | Byte* ptr = nullptr; // only emulate the writing and just count the bytes needed |
305 | 0 | int nBytesTiling = 0; |
306 | |
|
307 | 0 | if (!WriteTiles(arr, &ptr, nBytesTiling, m_zMinVec, m_zMaxVec)) // also fills the min max ranges |
308 | 0 | return 0; |
309 | | |
310 | 0 | m_headerInfo.zMin = *std::min_element(m_zMinVec.begin(), m_zMinVec.end()); |
311 | 0 | m_headerInfo.zMax = *std::max_element(m_zMaxVec.begin(), m_zMaxVec.end()); |
312 | |
|
313 | 0 | if (m_headerInfo.zMin == m_headerInfo.zMax) // image is const |
314 | 0 | return nBytesHeaderMask; |
315 | | |
316 | 0 | int nDim = m_headerInfo.nDim; |
317 | |
|
318 | 0 | if (m_headerInfo.version >= 4) |
319 | 0 | { |
320 | | // add the min max ranges behind the mask and before the main data; |
321 | | // so we do not write it if no valid pixel or all same value const |
322 | 0 | m_headerInfo.blobSize += 2 * nDim * sizeof(T); |
323 | |
|
324 | 0 | bool minMaxEqual = false; |
325 | 0 | if (!CheckMinMaxRanges(minMaxEqual)) |
326 | 0 | return 0; |
327 | | |
328 | 0 | if (minMaxEqual) |
329 | 0 | return m_headerInfo.blobSize; // all nDim bands are const |
330 | 0 | } |
331 | | |
332 | | // data |
333 | 0 | m_imageEncodeMode = IEM_Tiling; |
334 | 0 | int nBytesData = nBytesTiling; |
335 | 0 | int nBytesHuffman = 0; |
336 | |
|
337 | 0 | if (m_headerInfo.TryHuffman()) |
338 | 0 | { |
339 | 0 | ImageEncodeMode huffmanEncMode; |
340 | 0 | ComputeHuffmanCodes(arr, nBytesHuffman, huffmanEncMode, m_huffmanCodes); // save Huffman codes for later use |
341 | |
|
342 | 0 | if (!m_huffmanCodes.empty() && nBytesHuffman < nBytesTiling) |
343 | 0 | { |
344 | 0 | m_imageEncodeMode = huffmanEncMode; |
345 | 0 | nBytesData = nBytesHuffman; |
346 | 0 | } |
347 | 0 | else |
348 | 0 | m_huffmanCodes.resize(0); |
349 | 0 | } |
350 | |
|
351 | 0 | m_writeDataOneSweep = false; |
352 | 0 | int nBytesDataOneSweep = (int)(numValid * nDim * sizeof(T)); |
353 | |
|
354 | 0 | { |
355 | | // try with double block size to reduce block header overhead, if |
356 | 0 | if ( (nBytesTiling * 8 < numTotal * nDim * 2) // resulting bit rate < x (2 bpp) |
357 | 0 | && (nBytesTiling < 4 * nBytesDataOneSweep) // bit stuffing is effective |
358 | 0 | && (nBytesHuffman == 0 || nBytesTiling < 2 * nBytesHuffman) ) // not much worse than huffman (otherwise huffman wins anyway) |
359 | 0 | { |
360 | 0 | m_headerInfo.microBlockSize = m_microBlockSize * 2; |
361 | |
|
362 | 0 | std::vector<double> zMinVec, zMaxVec; |
363 | 0 | int nBytes2 = 0; |
364 | 0 | if (!WriteTiles(arr, &ptr, nBytes2, zMinVec, zMaxVec)) // no huffman in here anymore |
365 | 0 | return 0; |
366 | | |
367 | 0 | if (nBytes2 <= nBytesData) |
368 | 0 | { |
369 | 0 | nBytesData = nBytes2; |
370 | 0 | m_imageEncodeMode = IEM_Tiling; |
371 | 0 | m_huffmanCodes.resize(0); |
372 | 0 | } |
373 | 0 | else |
374 | 0 | { |
375 | 0 | m_headerInfo.microBlockSize = m_microBlockSize; // reset to orig |
376 | 0 | } |
377 | 0 | } |
378 | 0 | } |
379 | | |
380 | 0 | if (m_headerInfo.TryHuffman()) |
381 | 0 | nBytesData += 1; // flag for image encode mode |
382 | |
|
383 | 0 | if (nBytesDataOneSweep <= nBytesData) |
384 | 0 | { |
385 | 0 | m_writeDataOneSweep = true; // fallback: write data binary uncompressed in one sweep |
386 | 0 | m_headerInfo.blobSize += 1 + nBytesDataOneSweep; // header, mask, min max ranges, flag, data one sweep |
387 | 0 | } |
388 | 0 | else |
389 | 0 | { |
390 | 0 | m_writeDataOneSweep = false; |
391 | 0 | m_headerInfo.blobSize += 1 + nBytesData; // header, mask, min max ranges, flag(s), data |
392 | 0 | } |
393 | |
|
394 | 0 | return m_headerInfo.blobSize; |
395 | 0 | } Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<signed char>(signed char const*, double, bool) Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<unsigned char>(unsigned char const*, double, bool) Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<short>(short const*, double, bool) Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<unsigned short>(unsigned short const*, double, bool) Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<int>(int const*, double, bool) Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<unsigned int>(unsigned int const*, double, bool) Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<float>(float const*, double, bool) Unexecuted instantiation: unsigned int GDAL_LercNS::Lerc2::ComputeNumBytesNeededToWrite<double>(double const*, double, bool) |
396 | | |
397 | | // -------------------------------------------------------------------------- ; |
398 | | |
399 | | template<class T> |
400 | | bool Lerc2::Encode(const T* arr, Byte** ppByte) |
401 | 0 | { |
402 | 0 | if (!arr || !ppByte || !IsLittleEndianSystem()) |
403 | 0 | return false; |
404 | | |
405 | 0 | Byte* ptrBlob = *ppByte; // keep a ptr to the start of the blob |
406 | |
|
407 | 0 | if (!WriteHeader(ppByte, m_headerInfo)) |
408 | 0 | return false; |
409 | | |
410 | 0 | if (!WriteMask(ppByte)) |
411 | 0 | return false; |
412 | | |
413 | 0 | if (m_headerInfo.numValidPixel == 0 || m_headerInfo.zMin == m_headerInfo.zMax) |
414 | 0 | { |
415 | 0 | return DoChecksOnEncode(ptrBlob, *ppByte); |
416 | 0 | } |
417 | | |
418 | 0 | if (m_headerInfo.version >= 4) |
419 | 0 | { |
420 | 0 | if (!WriteMinMaxRanges(arr, ppByte)) |
421 | 0 | return false; |
422 | | |
423 | 0 | bool minMaxEqual = false; |
424 | 0 | if (!CheckMinMaxRanges(minMaxEqual)) |
425 | 0 | return false; |
426 | | |
427 | 0 | if (minMaxEqual) |
428 | 0 | return DoChecksOnEncode(ptrBlob, *ppByte); |
429 | 0 | } |
430 | | |
431 | 0 | **ppByte = m_writeDataOneSweep ? 1 : 0; // write flag |
432 | 0 | (*ppByte)++; |
433 | |
|
434 | 0 | if (!m_writeDataOneSweep) |
435 | 0 | { |
436 | 0 | if (m_headerInfo.TryHuffman()) |
437 | 0 | { |
438 | 0 | **ppByte = (Byte)m_imageEncodeMode; // Huffman or tiling encode mode |
439 | 0 | (*ppByte)++; |
440 | |
|
441 | 0 | if (!m_huffmanCodes.empty()) // Huffman, no tiling |
442 | 0 | { |
443 | 0 | if (m_imageEncodeMode != IEM_DeltaHuffman && m_imageEncodeMode != IEM_Huffman) |
444 | 0 | return false; |
445 | | |
446 | 0 | if (!EncodeHuffman(arr, ppByte)) // data bit stuffed |
447 | 0 | return false; |
448 | | |
449 | 0 | return DoChecksOnEncode(ptrBlob, *ppByte); |
450 | 0 | } |
451 | 0 | } |
452 | | |
453 | 0 | int numBytes = 0; |
454 | 0 | std::vector<double> zMinVec, zMaxVec; |
455 | 0 | if (!WriteTiles(arr, ppByte, numBytes, zMinVec, zMaxVec)) |
456 | 0 | return false; |
457 | 0 | } |
458 | 0 | else |
459 | 0 | { |
460 | 0 | if (!WriteDataOneSweep(arr, ppByte)) |
461 | 0 | return false; |
462 | 0 | } |
463 | | |
464 | 0 | return DoChecksOnEncode(ptrBlob, *ppByte); |
465 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<signed char>(signed char const*, unsigned char**) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<unsigned char>(unsigned char const*, unsigned char**) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<short>(short const*, unsigned char**) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<unsigned short>(unsigned short const*, unsigned char**) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<int>(int const*, unsigned char**) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<unsigned int>(unsigned int const*, unsigned char**) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<float>(float const*, unsigned char**) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Encode<double>(double const*, unsigned char**) |
466 | | |
467 | | // -------------------------------------------------------------------------- ; |
468 | | |
469 | | template<class T> |
470 | | bool Lerc2::Decode(const Byte** ppByte, size_t& nBytesRemaining, T* arr, Byte* pMaskBits) |
471 | 0 | { |
472 | 0 | if (!arr || !ppByte || !IsLittleEndianSystem()) |
473 | 0 | return false; |
474 | | |
475 | 0 | const Byte* ptrBlob = *ppByte; // keep a ptr to the start of the blob |
476 | 0 | size_t nBytesRemaining00 = nBytesRemaining; |
477 | |
|
478 | 0 | if (!ReadHeader(ppByte, nBytesRemaining, m_headerInfo)) |
479 | 0 | return false; |
480 | | |
481 | 0 | if (nBytesRemaining00 < (size_t)m_headerInfo.blobSize) |
482 | 0 | return false; |
483 | | |
484 | 0 | if (m_headerInfo.version >= 3) |
485 | 0 | { |
486 | 0 | int nBytes = (int)(FileKey().length() + sizeof(int) + sizeof(unsigned int)); // start right after the checksum entry |
487 | 0 | if (m_headerInfo.blobSize < nBytes) |
488 | 0 | return false; |
489 | 0 | unsigned int checksum = ComputeChecksumFletcher32(ptrBlob + nBytes, m_headerInfo.blobSize - nBytes); |
490 | 0 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
491 | | // For fuzzing, ignore checksum verification |
492 | 0 | (void)checksum; |
493 | | #else |
494 | | if (checksum != m_headerInfo.checksum) |
495 | | return false; |
496 | | #endif |
497 | 0 | } |
498 | | |
499 | 0 | if (!ReadMask(ppByte, nBytesRemaining)) |
500 | 0 | return false; |
501 | | |
502 | 0 | if (pMaskBits) // return proper mask bits even if they were not stored |
503 | 0 | memcpy(pMaskBits, m_bitMask.Bits(), m_bitMask.Size()); |
504 | |
|
505 | 0 | memset(arr, 0, m_headerInfo.nCols * m_headerInfo.nRows * m_headerInfo.nDim * sizeof(T)); |
506 | |
|
507 | 0 | if (m_headerInfo.numValidPixel == 0) |
508 | 0 | return true; |
509 | | |
510 | 0 | if (m_headerInfo.zMin == m_headerInfo.zMax) // image is const |
511 | 0 | { |
512 | 0 | if (!FillConstImage(arr)) |
513 | 0 | return false; |
514 | | |
515 | 0 | return true; |
516 | 0 | } |
517 | | |
518 | 0 | if (m_headerInfo.version >= 4) |
519 | 0 | { |
520 | 0 | if (!ReadMinMaxRanges(ppByte, nBytesRemaining, arr)) |
521 | 0 | return false; |
522 | | |
523 | 0 | bool minMaxEqual = false; |
524 | 0 | if (!CheckMinMaxRanges(minMaxEqual)) |
525 | 0 | return false; |
526 | | |
527 | 0 | if (minMaxEqual) // if all bands are const, fill outgoing and done |
528 | 0 | { |
529 | 0 | if (!FillConstImage(arr)) |
530 | 0 | return false; |
531 | | |
532 | 0 | return true; // done |
533 | 0 | } |
534 | 0 | } |
535 | | |
536 | 0 | if (nBytesRemaining < 1) |
537 | 0 | return false; |
538 | | |
539 | 0 | Byte readDataOneSweep = **ppByte; // read flag |
540 | 0 | (*ppByte)++; |
541 | 0 | nBytesRemaining--; |
542 | |
|
543 | 0 | if (!readDataOneSweep) |
544 | 0 | { |
545 | 0 | if (m_headerInfo.TryHuffman()) |
546 | 0 | { |
547 | 0 | if (nBytesRemaining < 1) |
548 | 0 | return false; |
549 | | |
550 | 0 | Byte flag = **ppByte; // read flag Huffman / Lerc2 |
551 | 0 | (*ppByte)++; |
552 | 0 | nBytesRemaining--; |
553 | |
|
554 | 0 | if (flag > 2 || (m_headerInfo.version < 4 && flag > 1)) |
555 | 0 | return false; |
556 | | |
557 | 0 | m_imageEncodeMode = (ImageEncodeMode)flag; |
558 | |
|
559 | 0 | if (m_imageEncodeMode == IEM_DeltaHuffman || m_imageEncodeMode == IEM_Huffman) |
560 | 0 | { |
561 | 0 | if (!DecodeHuffman(ppByte, nBytesRemaining, arr)) |
562 | 0 | return false; |
563 | | |
564 | 0 | return true; // done. |
565 | 0 | } |
566 | 0 | } |
567 | | |
568 | 0 | if (!ReadTiles(ppByte, nBytesRemaining, arr)) |
569 | 0 | return false; |
570 | 0 | } |
571 | 0 | else |
572 | 0 | { |
573 | 0 | if (!ReadDataOneSweep(ppByte, nBytesRemaining, arr)) |
574 | 0 | return false; |
575 | 0 | } |
576 | | |
577 | 0 | return true; |
578 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<signed char>(unsigned char const**, unsigned long&, signed char*, unsigned char*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<unsigned char>(unsigned char const**, unsigned long&, unsigned char*, unsigned char*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<short>(unsigned char const**, unsigned long&, short*, unsigned char*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<unsigned short>(unsigned char const**, unsigned long&, unsigned short*, unsigned char*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<int>(unsigned char const**, unsigned long&, int*, unsigned char*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<unsigned int>(unsigned char const**, unsigned long&, unsigned int*, unsigned char*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<float>(unsigned char const**, unsigned long&, float*, unsigned char*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Decode<double>(unsigned char const**, unsigned long&, double*, unsigned char*) |
579 | | |
580 | | // -------------------------------------------------------------------------- ; |
581 | | // -------------------------------------------------------------------------- ; |
582 | | |
583 | | inline |
584 | | void Lerc2::AddUIntToCounts(int* pCounts, unsigned int val, int nBits) |
585 | 0 | { |
586 | 0 | pCounts[0] += val & 1; |
587 | 0 | for (int i = 1; i < nBits; i++) |
588 | 0 | pCounts[i] += (val >>= 1) & 1; |
589 | 0 | } |
590 | | |
591 | | // -------------------------------------------------------------------------- ; |
592 | | |
593 | | inline |
594 | | void Lerc2::AddIntToCounts(int* pCounts, int val, int nBits) |
595 | 0 | { |
596 | 0 | pCounts[0] += val & 1; |
597 | 0 | for (int i = 1; i < nBits; i++) |
598 | 0 | pCounts[i] += (val >>= 1) & 1; |
599 | 0 | } |
600 | | |
601 | | // -------------------------------------------------------------------------- ; |
602 | | |
603 | | // for the theory and math, see |
604 | | // https://pdfs.semanticscholar.org/d064/2e2ad1a4c3b445b0d795770f604a5d9e269c.pdf |
605 | | |
606 | | template<class T> |
607 | | bool Lerc2::TryBitPlaneCompression(const T* data, double eps, double& newMaxZError) const |
608 | 0 | { |
609 | 0 | newMaxZError = 0; // lossless is the obvious fallback |
610 | |
|
611 | 0 | if (!data || eps <= 0) |
612 | 0 | return false; |
613 | | |
614 | 0 | const HeaderInfo& hd = m_headerInfo; |
615 | 0 | const int nDim = hd.nDim; |
616 | 0 | const int maxShift = 8 * GetDataTypeSize(hd.dt); |
617 | 0 | const int minCnt = 5000; |
618 | |
|
619 | 0 | if (hd.numValidPixel < minCnt) // not enough data for good stats |
620 | 0 | return false; |
621 | | |
622 | 0 | std::vector<int> cntDiffVec(nDim * maxShift, 0); |
623 | 0 | int cnt = 0; |
624 | |
|
625 | 0 | if (nDim == 1 && hd.numValidPixel == hd.nCols * hd.nRows) // special but common case |
626 | 0 | { |
627 | 0 | if (hd.dt == DT_Byte || hd.dt == DT_UShort || hd.dt == DT_UInt) // unsigned int |
628 | 0 | { |
629 | 0 | for (int i = 0; i < hd.nRows - 1; i++) |
630 | 0 | for (int k = i * hd.nCols, j = 0; j < hd.nCols - 1; j++, k++) |
631 | 0 | { |
632 | 0 | unsigned int c = ((unsigned int)data[k]) ^ ((unsigned int)data[k + 1]); |
633 | 0 | AddUIntToCounts(&cntDiffVec[0], c, maxShift); |
634 | 0 | cnt++; |
635 | 0 | c = ((unsigned int)data[k]) ^ ((unsigned int)data[k + hd.nCols]); |
636 | 0 | AddUIntToCounts(&cntDiffVec[0], c, maxShift); |
637 | 0 | cnt++; |
638 | 0 | } |
639 | 0 | } |
640 | 0 | else if (hd.dt == DT_Char || hd.dt == DT_Short || hd.dt == DT_Int) // signed int |
641 | 0 | { |
642 | 0 | for (int i = 0; i < hd.nRows - 1; i++) |
643 | 0 | for (int k = i * hd.nCols, j = 0; j < hd.nCols - 1; j++, k++) |
644 | 0 | { |
645 | 0 | int c = ((int)data[k]) ^ ((int)data[k + 1]); |
646 | 0 | AddIntToCounts(&cntDiffVec[0], c, maxShift); |
647 | 0 | cnt++; |
648 | 0 | c = ((int)data[k]) ^ ((int)data[k + hd.nCols]); |
649 | 0 | AddIntToCounts(&cntDiffVec[0], c, maxShift); |
650 | 0 | cnt++; |
651 | 0 | } |
652 | 0 | } |
653 | 0 | else |
654 | 0 | return false; // unsupported data type |
655 | 0 | } |
656 | | |
657 | 0 | else // general case: nDim > 1 or not all pixel valid |
658 | 0 | { |
659 | 0 | if (hd.dt == DT_Byte || hd.dt == DT_UShort || hd.dt == DT_UInt) // unsigned int |
660 | 0 | { |
661 | 0 | for (int k = 0, m0 = 0, i = 0; i < hd.nRows; i++) |
662 | 0 | for (int j = 0; j < hd.nCols; j++, k++, m0 += nDim) |
663 | 0 | if (m_bitMask.IsValid(k)) |
664 | 0 | { |
665 | 0 | if (j < hd.nCols - 1 && m_bitMask.IsValid(k + 1)) // hori |
666 | 0 | { |
667 | 0 | for (int s0 = 0, iDim = 0; iDim < nDim; iDim++, s0 += maxShift) |
668 | 0 | { |
669 | 0 | unsigned int c = ((unsigned int)data[m0 + iDim]) ^ ((unsigned int)data[m0 + iDim + nDim]); |
670 | 0 | AddUIntToCounts(&cntDiffVec[s0], c, maxShift); |
671 | 0 | } |
672 | 0 | cnt++; |
673 | 0 | } |
674 | 0 | if (i < hd.nRows - 1 && m_bitMask.IsValid(k + hd.nCols)) // vert |
675 | 0 | { |
676 | 0 | for (int s0 = 0, iDim = 0; iDim < nDim; iDim++, s0 += maxShift) |
677 | 0 | { |
678 | 0 | unsigned int c = ((unsigned int)data[m0 + iDim]) ^ ((unsigned int)data[m0 + iDim + nDim * hd.nCols]); |
679 | 0 | AddUIntToCounts(&cntDiffVec[s0], c, maxShift); |
680 | 0 | } |
681 | 0 | cnt++; |
682 | 0 | } |
683 | 0 | } |
684 | 0 | } |
685 | 0 | else if (hd.dt == DT_Char || hd.dt == DT_Short || hd.dt == DT_Int) // signed int |
686 | 0 | { |
687 | 0 | for (int k = 0, m0 = 0, i = 0; i < hd.nRows; i++) |
688 | 0 | for (int j = 0; j < hd.nCols; j++, k++, m0 += nDim) |
689 | 0 | if (m_bitMask.IsValid(k)) |
690 | 0 | { |
691 | 0 | if (j < hd.nCols - 1 && m_bitMask.IsValid(k + 1)) // hori |
692 | 0 | { |
693 | 0 | for (int s0 = 0, iDim = 0; iDim < nDim; iDim++, s0 += maxShift) |
694 | 0 | { |
695 | 0 | int c = ((int)data[m0 + iDim]) ^ ((int)data[m0 + iDim + nDim]); |
696 | 0 | AddIntToCounts(&cntDiffVec[s0], c, maxShift); |
697 | 0 | } |
698 | 0 | cnt++; |
699 | 0 | } |
700 | 0 | if (i < hd.nRows - 1 && m_bitMask.IsValid(k + hd.nCols)) // vert |
701 | 0 | { |
702 | 0 | for (int s0 = 0, iDim = 0; iDim < nDim; iDim++, s0 += maxShift) |
703 | 0 | { |
704 | 0 | int c = ((int)data[m0 + iDim]) ^ ((int)data[m0 + iDim + nDim * hd.nCols]); |
705 | 0 | AddIntToCounts(&cntDiffVec[s0], c, maxShift); |
706 | 0 | } |
707 | 0 | cnt++; |
708 | 0 | } |
709 | 0 | } |
710 | 0 | } |
711 | 0 | else |
712 | 0 | return false; // unsupported data type |
713 | 0 | } |
714 | | |
715 | 0 | if (cnt < minCnt) // not enough data for good stats |
716 | 0 | return false; |
717 | | |
718 | 0 | int nCutFound = 0, lastPlaneKept = 0; |
719 | 0 | const bool printAll = false; |
720 | |
|
721 | 0 | for (int s = maxShift - 1; s >= 0; s--) |
722 | 0 | { |
723 | 0 | if (printAll) printf("bit plane %2d: ", s); |
724 | 0 | bool bCrit = true; |
725 | |
|
726 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
727 | 0 | { |
728 | 0 | double x = cntDiffVec[iDim * maxShift + s]; |
729 | 0 | double n = cnt; |
730 | 0 | double m = x / n; |
731 | | //double stdDev = sqrt(x * x / n - m * m) / n; |
732 | | |
733 | | //printf(" %.4f +- %.4f ", (float)(2 * m), (float)(2 * stdDev)); |
734 | 0 | if (printAll) printf(" %.4f ", (float)(2 * m)); |
735 | |
|
736 | 0 | if (fabs(1 - 2 * m) >= eps) |
737 | 0 | bCrit = false; |
738 | 0 | } |
739 | 0 | if (printAll) printf("\n"); |
740 | |
|
741 | 0 | if (bCrit && nCutFound < 2) |
742 | 0 | { |
743 | 0 | if (nCutFound == 0) |
744 | 0 | lastPlaneKept = s; |
745 | |
|
746 | 0 | if (nCutFound == 1 && s < lastPlaneKept - 1) |
747 | 0 | { |
748 | 0 | lastPlaneKept = s; |
749 | 0 | nCutFound = 0; |
750 | 0 | if (printAll) printf(" reset "); |
751 | 0 | } |
752 | |
|
753 | 0 | nCutFound++; |
754 | 0 | if (printAll && nCutFound == 1) printf("\n"); |
755 | 0 | } |
756 | 0 | } |
757 | |
|
758 | 0 | lastPlaneKept = std::max(0, lastPlaneKept); |
759 | 0 | if (printAll) printf("%d \n", lastPlaneKept); |
760 | |
|
761 | 0 | newMaxZError = (1 << lastPlaneKept) >> 1; // turn lastPlaneKept into new maxZError |
762 | |
|
763 | 0 | return true; |
764 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<signed char>(signed char const*, double, double&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<unsigned char>(unsigned char const*, double, double&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<short>(short const*, double, double&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<unsigned short>(unsigned short const*, double, double&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<int>(int const*, double, double&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<unsigned int>(unsigned int const*, double, double&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<float>(float const*, double, double&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::TryBitPlaneCompression<double>(double const*, double, double&) const |
765 | | |
766 | | // -------------------------------------------------------------------------- ; |
767 | | |
768 | | template<class T> |
769 | | bool Lerc2::WriteDataOneSweep(const T* data, Byte** ppByte) const |
770 | 0 | { |
771 | 0 | if (!data || !ppByte) |
772 | 0 | return false; |
773 | | |
774 | 0 | Byte* ptr = (*ppByte); |
775 | 0 | const HeaderInfo& hd = m_headerInfo; |
776 | 0 | int nDim = hd.nDim; |
777 | 0 | int len = nDim * sizeof(T); |
778 | |
|
779 | 0 | for (int k = 0, m0 = 0, i = 0; i < hd.nRows; i++) |
780 | 0 | for (int j = 0; j < hd.nCols; j++, k++, m0 += nDim) |
781 | 0 | if (m_bitMask.IsValid(k)) |
782 | 0 | { |
783 | 0 | memcpy(ptr, &data[m0], len); |
784 | 0 | ptr += len; |
785 | 0 | } |
786 | |
|
787 | 0 | (*ppByte) = ptr; |
788 | 0 | return true; |
789 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<signed char>(signed char const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<unsigned char>(unsigned char const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<short>(short const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<unsigned short>(unsigned short const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<int>(int const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<unsigned int>(unsigned int const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<float>(float const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteDataOneSweep<double>(double const*, unsigned char**) const |
790 | | |
791 | | // -------------------------------------------------------------------------- ; |
792 | | |
793 | | template<class T> |
794 | | bool Lerc2::ReadDataOneSweep(const Byte** ppByte, size_t& nBytesRemaining, T* data) const |
795 | 0 | { |
796 | 0 | if (!data || !ppByte || !(*ppByte)) |
797 | 0 | return false; |
798 | | |
799 | 0 | const Byte* ptr = (*ppByte); |
800 | 0 | const HeaderInfo& hd = m_headerInfo; |
801 | 0 | int nDim = hd.nDim; |
802 | 0 | int len = nDim * sizeof(T); |
803 | |
|
804 | 0 | size_t nValidPix = (size_t)m_bitMask.CountValidBits(); |
805 | |
|
806 | 0 | if (nBytesRemaining < nValidPix * len) |
807 | 0 | return false; |
808 | | |
809 | 0 | for (int k = 0, m0 = 0, i = 0; i < hd.nRows; i++) |
810 | 0 | for (int j = 0; j < hd.nCols; j++, k++, m0 += nDim) |
811 | 0 | if (m_bitMask.IsValid(k)) |
812 | 0 | { |
813 | 0 | memcpy(&data[m0], ptr, len); |
814 | 0 | ptr += len; |
815 | 0 | } |
816 | |
|
817 | 0 | (*ppByte) = ptr; |
818 | 0 | nBytesRemaining -= nValidPix * len; |
819 | |
|
820 | 0 | return true; |
821 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<signed char>(unsigned char const**, unsigned long&, signed char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<unsigned char>(unsigned char const**, unsigned long&, unsigned char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<short>(unsigned char const**, unsigned long&, short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<unsigned short>(unsigned char const**, unsigned long&, unsigned short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<int>(unsigned char const**, unsigned long&, int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<unsigned int>(unsigned char const**, unsigned long&, unsigned int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<float>(unsigned char const**, unsigned long&, float*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadDataOneSweep<double>(unsigned char const**, unsigned long&, double*) const |
822 | | |
823 | | // -------------------------------------------------------------------------- ; |
824 | | |
825 | | template<class T> |
826 | | bool Lerc2::WriteTiles(const T* data, Byte** ppByte, int& numBytes, std::vector<double>& zMinVec, std::vector<double>& zMaxVec) const |
827 | 0 | { |
828 | 0 | if (!data || !ppByte) |
829 | 0 | return false; |
830 | | |
831 | 0 | numBytes = 0; |
832 | 0 | int numBytesLerc = 0; |
833 | |
|
834 | 0 | std::vector<unsigned int> quantVec; |
835 | 0 | std::vector<std::pair<unsigned int, unsigned int> > sortedQuantVec; |
836 | |
|
837 | 0 | const HeaderInfo& hd = m_headerInfo; |
838 | 0 | int mbSize = hd.microBlockSize; |
839 | 0 | int nDim = hd.nDim; |
840 | |
|
841 | 0 | std::vector<T> dataVec(mbSize * mbSize, 0); |
842 | 0 | T* dataBuf = &dataVec[0]; |
843 | |
|
844 | 0 | zMinVec.assign(nDim, DBL_MAX); |
845 | 0 | zMaxVec.assign(nDim, -DBL_MAX); |
846 | |
|
847 | 0 | int numTilesVert = (hd.nRows + mbSize - 1) / mbSize; |
848 | 0 | int numTilesHori = (hd.nCols + mbSize - 1) / mbSize; |
849 | |
|
850 | 0 | for (int iTile = 0; iTile < numTilesVert; iTile++) |
851 | 0 | { |
852 | 0 | int tileH = mbSize; |
853 | 0 | int i0 = iTile * tileH; |
854 | 0 | if (iTile == numTilesVert - 1) |
855 | 0 | tileH = hd.nRows - i0; |
856 | |
|
857 | 0 | for (int jTile = 0; jTile < numTilesHori; jTile++) |
858 | 0 | { |
859 | 0 | int tileW = mbSize; |
860 | 0 | int j0 = jTile * tileW; |
861 | 0 | if (jTile == numTilesHori - 1) |
862 | 0 | tileW = hd.nCols - j0; |
863 | |
|
864 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
865 | 0 | { |
866 | 0 | T zMin = 0, zMax = 0; |
867 | 0 | int numValidPixel = 0; |
868 | 0 | bool tryLut = false; |
869 | |
|
870 | 0 | if (!GetValidDataAndStats(data, i0, i0 + tileH, j0, j0 + tileW, iDim, dataBuf, zMin, zMax, numValidPixel, tryLut)) |
871 | 0 | return false; |
872 | | |
873 | 0 | if (numValidPixel > 0) |
874 | 0 | { |
875 | 0 | zMinVec[iDim] = (std::min)(zMinVec[iDim], (double)zMin); |
876 | 0 | zMaxVec[iDim] = (std::max)(zMaxVec[iDim], (double)zMax); |
877 | 0 | } |
878 | | |
879 | | //tryLut = false; |
880 | | |
881 | | // if needed, quantize the data here once |
882 | 0 | if ((*ppByte || tryLut) && NeedToQuantize(numValidPixel, zMin, zMax)) |
883 | 0 | { |
884 | 0 | if (!Quantize(dataBuf, numValidPixel, zMin, quantVec)) |
885 | 0 | return false; |
886 | | |
887 | 0 | if (tryLut) |
888 | 0 | SortQuantArray(quantVec, sortedQuantVec); |
889 | 0 | } |
890 | | |
891 | 0 | BlockEncodeMode blockEncodeMode; |
892 | 0 | int numBytesNeeded = NumBytesTile(numValidPixel, zMin, zMax, tryLut, blockEncodeMode, sortedQuantVec); |
893 | 0 | numBytesLerc += numBytesNeeded; |
894 | |
|
895 | 0 | if (*ppByte) |
896 | 0 | { |
897 | 0 | int numBytesWritten = 0; |
898 | |
|
899 | 0 | if (!WriteTile(dataBuf, numValidPixel, ppByte, numBytesWritten, j0, zMin, zMax, quantVec, blockEncodeMode, sortedQuantVec)) |
900 | 0 | return false; |
901 | | |
902 | 0 | if (numBytesWritten != numBytesNeeded) |
903 | 0 | return false; |
904 | 0 | } |
905 | 0 | } |
906 | 0 | } |
907 | 0 | } |
908 | | |
909 | 0 | numBytes += numBytesLerc; |
910 | 0 | return true; |
911 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<signed char>(signed char const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<unsigned char>(unsigned char const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<short>(short const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<unsigned short>(unsigned short const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<int>(int const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<unsigned int>(unsigned int const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<float>(float const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTiles<double>(double const*, unsigned char**, int&, std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >&) const |
912 | | |
913 | | // -------------------------------------------------------------------------- ; |
914 | | |
915 | | template<class T> |
916 | | bool Lerc2::ReadTiles(const Byte** ppByte, size_t& nBytesRemaining, T* data) const |
917 | 0 | { |
918 | 0 | if (!data || !ppByte || !(*ppByte)) |
919 | 0 | return false; |
920 | | |
921 | 0 | std::vector<unsigned int> bufferVec; |
922 | |
|
923 | 0 | const HeaderInfo& hd = m_headerInfo; |
924 | 0 | int mbSize = hd.microBlockSize; |
925 | 0 | int nDim = hd.nDim; |
926 | |
|
927 | 0 | if (mbSize > 32) // fail gracefully in case of corrupted blob for old version <= 2 which had no checksum |
928 | 0 | return false; |
929 | | |
930 | 0 | if( mbSize <= 0 || hd.nRows < 0 || hd.nCols < 0 || |
931 | 0 | hd.nRows > std::numeric_limits<int>::max() - (mbSize - 1) || |
932 | 0 | hd.nCols > std::numeric_limits<int>::max() - (mbSize - 1) ) |
933 | 0 | { |
934 | 0 | return false; |
935 | 0 | } |
936 | 0 | int numTilesVert = (hd.nRows + mbSize - 1) / mbSize; |
937 | 0 | int numTilesHori = (hd.nCols + mbSize - 1) / mbSize; |
938 | |
|
939 | 0 | for (int iTile = 0; iTile < numTilesVert; iTile++) |
940 | 0 | { |
941 | 0 | int tileH = mbSize; |
942 | 0 | int i0 = iTile * tileH; |
943 | 0 | if (iTile == numTilesVert - 1) |
944 | 0 | tileH = hd.nRows - i0; |
945 | |
|
946 | 0 | for (int jTile = 0; jTile < numTilesHori; jTile++) |
947 | 0 | { |
948 | 0 | int tileW = mbSize; |
949 | 0 | int j0 = jTile * tileW; |
950 | 0 | if (jTile == numTilesHori - 1) |
951 | 0 | tileW = hd.nCols - j0; |
952 | |
|
953 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
954 | 0 | { |
955 | 0 | if (!ReadTile(ppByte, nBytesRemaining, data, i0, i0 + tileH, j0, j0 + tileW, iDim, bufferVec)) |
956 | 0 | return false; |
957 | 0 | } |
958 | 0 | } |
959 | 0 | } |
960 | | |
961 | 0 | return true; |
962 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<signed char>(unsigned char const**, unsigned long&, signed char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<unsigned char>(unsigned char const**, unsigned long&, unsigned char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<short>(unsigned char const**, unsigned long&, short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<unsigned short>(unsigned char const**, unsigned long&, unsigned short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<int>(unsigned char const**, unsigned long&, int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<unsigned int>(unsigned char const**, unsigned long&, unsigned int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<float>(unsigned char const**, unsigned long&, float*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTiles<double>(unsigned char const**, unsigned long&, double*) const |
963 | | |
964 | | // -------------------------------------------------------------------------- ; |
965 | | |
966 | | template<class T> |
967 | | bool Lerc2::GetValidDataAndStats(const T* data, int i0, int i1, int j0, int j1, int iDim, |
968 | | T* dataBuf, T& zMin, T& zMax, int& numValidPixel, bool& tryLut) const |
969 | 0 | { |
970 | 0 | const HeaderInfo& hd = m_headerInfo; |
971 | |
|
972 | 0 | if (!data || i0 < 0 || j0 < 0 || i1 > hd.nRows || j1 > hd.nCols || iDim < 0 || iDim > hd.nDim || !dataBuf) |
973 | 0 | return false; |
974 | | |
975 | 0 | zMin = 0; |
976 | 0 | zMax = 0; |
977 | 0 | tryLut = false; |
978 | |
|
979 | 0 | T prevVal = 0; |
980 | 0 | int cnt = 0, cntSameVal = 0; |
981 | 0 | int nDim = hd.nDim; |
982 | |
|
983 | 0 | if (hd.numValidPixel == hd.nCols * hd.nRows) // all valid, no mask |
984 | 0 | { |
985 | 0 | for (int i = i0; i < i1; i++) |
986 | 0 | { |
987 | 0 | int k = i * hd.nCols + j0; |
988 | 0 | int m = k * nDim + iDim; |
989 | |
|
990 | 0 | for (int j = j0; j < j1; j++, k++, m += nDim) |
991 | 0 | { |
992 | 0 | T val = data[m]; |
993 | 0 | dataBuf[cnt] = val; |
994 | |
|
995 | 0 | if (cnt > 0) |
996 | 0 | { |
997 | 0 | if (val < zMin) |
998 | 0 | zMin = val; |
999 | 0 | else if (val > zMax) |
1000 | 0 | zMax = val; |
1001 | |
|
1002 | 0 | if (val == prevVal) |
1003 | 0 | cntSameVal++; |
1004 | 0 | } |
1005 | 0 | else |
1006 | 0 | zMin = zMax = val; // init |
1007 | |
|
1008 | 0 | prevVal = val; |
1009 | 0 | cnt++; |
1010 | 0 | } |
1011 | 0 | } |
1012 | 0 | } |
1013 | 0 | else // not all valid, use mask |
1014 | 0 | { |
1015 | 0 | for (int i = i0; i < i1; i++) |
1016 | 0 | { |
1017 | 0 | int k = i * hd.nCols + j0; |
1018 | 0 | int m = k * nDim + iDim; |
1019 | |
|
1020 | 0 | for (int j = j0; j < j1; j++, k++, m += nDim) |
1021 | 0 | if (m_bitMask.IsValid(k)) |
1022 | 0 | { |
1023 | 0 | T val = data[m]; |
1024 | 0 | dataBuf[cnt] = val; |
1025 | |
|
1026 | 0 | if (cnt > 0) |
1027 | 0 | { |
1028 | 0 | if (val < zMin) |
1029 | 0 | zMin = val; |
1030 | 0 | else if (val > zMax) |
1031 | 0 | zMax = val; |
1032 | |
|
1033 | 0 | if (val == prevVal) |
1034 | 0 | cntSameVal++; |
1035 | 0 | } |
1036 | 0 | else |
1037 | 0 | zMin = zMax = val; // init |
1038 | |
|
1039 | 0 | prevVal = val; |
1040 | 0 | cnt++; |
1041 | 0 | } |
1042 | 0 | } |
1043 | 0 | } |
1044 | |
|
1045 | 0 | if (cnt > 4) |
1046 | 0 | tryLut = (zMax > zMin + hd.maxZError) && (2 * cntSameVal > cnt); |
1047 | |
|
1048 | 0 | numValidPixel = cnt; |
1049 | 0 | return true; |
1050 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<signed char>(signed char const*, int, int, int, int, int, signed char*, signed char&, signed char&, int&, bool&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<unsigned char>(unsigned char const*, int, int, int, int, int, unsigned char*, unsigned char&, unsigned char&, int&, bool&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<short>(short const*, int, int, int, int, int, short*, short&, short&, int&, bool&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<unsigned short>(unsigned short const*, int, int, int, int, int, unsigned short*, unsigned short&, unsigned short&, int&, bool&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<int>(int const*, int, int, int, int, int, int*, int&, int&, int&, bool&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<unsigned int>(unsigned int const*, int, int, int, int, int, unsigned int*, unsigned int&, unsigned int&, int&, bool&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<float>(float const*, int, int, int, int, int, float*, float&, float&, int&, bool&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::GetValidDataAndStats<double>(double const*, int, int, int, int, int, double*, double&, double&, int&, bool&) const |
1051 | | |
1052 | | // -------------------------------------------------------------------------- ; |
1053 | | |
1054 | | inline double Lerc2::ComputeMaxVal(double zMin, double zMax, double maxZError) |
1055 | 0 | { |
1056 | 0 | double fac = 1 / (2 * maxZError); // must match the code in Decode(), don't touch it |
1057 | 0 | return (zMax - zMin) * fac; |
1058 | 0 | } |
1059 | | |
1060 | | // -------------------------------------------------------------------------- ; |
1061 | | |
1062 | | template<class T> |
1063 | | bool Lerc2::NeedToQuantize(int numValidPixel, T zMin, T zMax) const |
1064 | 0 | { |
1065 | 0 | if (numValidPixel == 0 || m_headerInfo.maxZError == 0) |
1066 | 0 | return false; |
1067 | | |
1068 | 0 | double maxVal = ComputeMaxVal(zMin, zMax, m_headerInfo.maxZError); |
1069 | 0 | return !(maxVal > m_maxValToQuantize || (unsigned int)(maxVal + 0.5) == 0); |
1070 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<signed char>(int, signed char, signed char) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<unsigned char>(int, unsigned char, unsigned char) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<short>(int, short, short) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<unsigned short>(int, unsigned short, unsigned short) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<int>(int, int, int) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<unsigned int>(int, unsigned int, unsigned int) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<float>(int, float, float) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::NeedToQuantize<double>(int, double, double) const |
1071 | | |
1072 | | // -------------------------------------------------------------------------- ; |
1073 | | |
1074 | | template<class T> |
1075 | | bool Lerc2::Quantize(const T* dataBuf, int num, T zMin, std::vector<unsigned int>& quantVec) const |
1076 | 0 | { |
1077 | 0 | quantVec.resize(num); |
1078 | |
|
1079 | 0 | if (m_headerInfo.dt < DT_Float && m_headerInfo.maxZError == 0.5) // int lossless |
1080 | 0 | { |
1081 | 0 | for (int i = 0; i < num; i++) |
1082 | 0 | quantVec[i] = (unsigned int)(dataBuf[i] - zMin); // ok, as char, short get promoted to int by C++ integral promotion rule |
1083 | 0 | } |
1084 | 0 | else // float and/or lossy |
1085 | 0 | { |
1086 | 0 | double scale = 1 / (2 * m_headerInfo.maxZError); |
1087 | 0 | double zMinDbl = (double)zMin; |
1088 | |
|
1089 | 0 | for (int i = 0; i < num; i++) |
1090 | 0 | quantVec[i] = (unsigned int)(((double)dataBuf[i] - zMinDbl) * scale + 0.5); // ok, consistent with ComputeMaxVal(...) |
1091 | | //quantVec[i] = (unsigned int)((dataBuf[i] - zMin) * scale + 0.5); // bad, not consistent with ComputeMaxVal(...) |
1092 | 0 | } |
1093 | |
|
1094 | 0 | return true; |
1095 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<signed char>(signed char const*, int, signed char, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<unsigned char>(unsigned char const*, int, unsigned char, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<short>(short const*, int, short, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<unsigned short>(unsigned short const*, int, unsigned short, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<int>(int const*, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<unsigned int>(unsigned int const*, int, unsigned int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<float>(float const*, int, float, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::Quantize<double>(double const*, int, double, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const |
1096 | | |
1097 | | // -------------------------------------------------------------------------- ; |
1098 | | |
1099 | | template<class T> |
1100 | | int Lerc2::NumBytesTile(int numValidPixel, T zMin, T zMax, bool tryLut, BlockEncodeMode& blockEncodeMode, |
1101 | | const std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec) const |
1102 | 0 | { |
1103 | 0 | blockEncodeMode = BEM_RawBinary; |
1104 | |
|
1105 | 0 | if (numValidPixel == 0 || (zMin == 0 && zMax == 0)) |
1106 | 0 | return 1; |
1107 | | |
1108 | 0 | double maxVal = 0, maxZError = m_headerInfo.maxZError; |
1109 | 0 | int nBytesRaw = (int)(1 + numValidPixel * sizeof(T)); |
1110 | |
|
1111 | 0 | if ((maxZError == 0 && zMax > zMin) |
1112 | 0 | || (maxZError > 0 && (maxVal = ComputeMaxVal(zMin, zMax, maxZError)) > m_maxValToQuantize)) |
1113 | 0 | { |
1114 | 0 | return nBytesRaw; |
1115 | 0 | } |
1116 | 0 | else |
1117 | 0 | { |
1118 | 0 | DataType dtUsed; |
1119 | 0 | TypeCode(zMin, dtUsed); |
1120 | 0 | int nBytes = 1 + GetDataTypeSize(dtUsed); |
1121 | |
|
1122 | 0 | unsigned int maxElem = (unsigned int)(maxVal + 0.5); |
1123 | 0 | if (maxElem > 0) |
1124 | 0 | { |
1125 | 0 | nBytes += (!tryLut) ? m_bitStuffer2.ComputeNumBytesNeededSimple(numValidPixel, maxElem) |
1126 | 0 | : m_bitStuffer2.ComputeNumBytesNeededLut(sortedQuantVec, tryLut); |
1127 | 0 | } |
1128 | |
|
1129 | 0 | if (nBytes < nBytesRaw) |
1130 | 0 | blockEncodeMode = (!tryLut || maxElem == 0) ? BEM_BitStuffSimple : BEM_BitStuffLUT; |
1131 | 0 | else |
1132 | 0 | nBytes = nBytesRaw; |
1133 | |
|
1134 | 0 | return nBytes; |
1135 | 0 | } |
1136 | 0 | } Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<signed char>(int, signed char, signed char, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<unsigned char>(int, unsigned char, unsigned char, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<short>(int, short, short, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<unsigned short>(int, unsigned short, unsigned short, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<int>(int, int, int, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<unsigned int>(int, unsigned int, unsigned int, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<float>(int, float, float, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::NumBytesTile<double>(int, double, double, bool, GDAL_LercNS::Lerc2::BlockEncodeMode&, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const |
1137 | | |
1138 | | // -------------------------------------------------------------------------- ; |
1139 | | |
1140 | | template<class T> |
1141 | | bool Lerc2::WriteTile(const T* dataBuf, int num, Byte** ppByte, int& numBytesWritten, int j0, T zMin, T zMax, |
1142 | | const std::vector<unsigned int>& quantVec, BlockEncodeMode blockEncodeMode, |
1143 | | const std::vector<std::pair<unsigned int, unsigned int> >& sortedQuantVec) const |
1144 | 0 | { |
1145 | 0 | Byte* ptr = *ppByte; |
1146 | 0 | Byte comprFlag = ((j0 >> 3) & 15) << 2; // use bits 2345 for integrity check |
1147 | |
|
1148 | 0 | if (num == 0 || (zMin == 0 && zMax == 0)) // special cases |
1149 | 0 | { |
1150 | 0 | *ptr++ = comprFlag | 2; // set compression flag to 2 to mark tile as constant 0 |
1151 | 0 | numBytesWritten = 1; |
1152 | 0 | *ppByte = ptr; |
1153 | 0 | return true; |
1154 | 0 | } |
1155 | | |
1156 | 0 | if (blockEncodeMode == BEM_RawBinary) |
1157 | 0 | { |
1158 | 0 | *ptr++ = comprFlag | 0; // write z's binary uncompressed |
1159 | |
|
1160 | 0 | memcpy(ptr, dataBuf, num * sizeof(T)); |
1161 | 0 | ptr += num * sizeof(T); |
1162 | 0 | } |
1163 | 0 | else |
1164 | 0 | { |
1165 | 0 | double maxVal = (m_headerInfo.maxZError > 0) ? ComputeMaxVal(zMin, zMax, m_headerInfo.maxZError) : 0; |
1166 | | |
1167 | | // write z's as int arr bit stuffed |
1168 | 0 | unsigned int maxElem = (unsigned int)(maxVal + 0.5); |
1169 | 0 | if (maxElem == 0) |
1170 | 0 | comprFlag |= 3; // set compression flag to 3 to mark tile as constant zMin |
1171 | 0 | else |
1172 | 0 | comprFlag |= 1; // use bit stuffing |
1173 | |
|
1174 | 0 | DataType dtUsed; |
1175 | 0 | int bits67 = TypeCode(zMin, dtUsed); |
1176 | 0 | comprFlag |= bits67 << 6; |
1177 | |
|
1178 | 0 | *ptr++ = comprFlag; |
1179 | |
|
1180 | 0 | if (!WriteVariableDataType(&ptr, (double)zMin, dtUsed)) |
1181 | 0 | return false; |
1182 | | |
1183 | 0 | if (maxElem > 0) |
1184 | 0 | { |
1185 | 0 | if ((int)quantVec.size() != num) |
1186 | 0 | return false; |
1187 | | |
1188 | 0 | if (blockEncodeMode == BEM_BitStuffSimple) |
1189 | 0 | { |
1190 | 0 | if (!m_bitStuffer2.EncodeSimple(&ptr, quantVec, m_headerInfo.version)) |
1191 | 0 | return false; |
1192 | 0 | } |
1193 | 0 | else if (blockEncodeMode == BEM_BitStuffLUT) |
1194 | 0 | { |
1195 | 0 | if (!m_bitStuffer2.EncodeLut(&ptr, sortedQuantVec, m_headerInfo.version)) |
1196 | 0 | return false; |
1197 | 0 | } |
1198 | 0 | else |
1199 | 0 | return false; |
1200 | 0 | } |
1201 | 0 | } |
1202 | | |
1203 | 0 | numBytesWritten = (int)(ptr - *ppByte); |
1204 | 0 | *ppByte = ptr; |
1205 | 0 | return true; |
1206 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<signed char>(signed char const*, int, unsigned char**, int&, int, signed char, signed char, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<unsigned char>(unsigned char const*, int, unsigned char**, int&, int, unsigned char, unsigned char, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<short>(short const*, int, unsigned char**, int&, int, short, short, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<unsigned short>(unsigned short const*, int, unsigned char**, int&, int, unsigned short, unsigned short, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<int>(int const*, int, unsigned char**, int&, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<unsigned int>(unsigned int const*, int, unsigned char**, int&, int, unsigned int, unsigned int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<float>(float const*, int, unsigned char**, int&, int, float, float, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteTile<double>(double const*, int, unsigned char**, int&, int, double, double, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&, GDAL_LercNS::Lerc2::BlockEncodeMode, std::__1::vector<std::__1::pair<unsigned int, unsigned int>, std::__1::allocator<std::__1::pair<unsigned int, unsigned int> > > const&) const |
1207 | | |
1208 | | // -------------------------------------------------------------------------- ; |
1209 | | |
1210 | | template<class T> |
1211 | | bool Lerc2::ReadTile(const Byte** ppByte, size_t& nBytesRemainingInOut, T* data, int i0, int i1, int j0, int j1, int iDim, |
1212 | | std::vector<unsigned int>& bufferVec) const |
1213 | 0 | { |
1214 | 0 | const Byte* ptr = *ppByte; |
1215 | 0 | size_t nBytesRemaining = nBytesRemainingInOut; |
1216 | |
|
1217 | 0 | if (nBytesRemaining < 1) |
1218 | 0 | return false; |
1219 | | |
1220 | 0 | Byte comprFlag = *ptr++; |
1221 | 0 | nBytesRemaining--; |
1222 | |
|
1223 | 0 | int bits67 = comprFlag >> 6; |
1224 | 0 | int testCode = (comprFlag >> 2) & 15; // use bits 2345 for integrity check |
1225 | 0 | if (testCode != ((j0 >> 3) & 15)) |
1226 | 0 | return false; |
1227 | | |
1228 | 0 | const HeaderInfo& hd = m_headerInfo; |
1229 | 0 | int nCols = hd.nCols; |
1230 | 0 | int nDim = hd.nDim; |
1231 | |
|
1232 | 0 | comprFlag &= 3; |
1233 | |
|
1234 | 0 | if (comprFlag == 2) // entire tile is constant 0 (all the valid pixels) |
1235 | 0 | { |
1236 | 0 | for (int i = i0; i < i1; i++) |
1237 | 0 | { |
1238 | 0 | int k = i * nCols + j0; |
1239 | 0 | int m = k * nDim + iDim; |
1240 | |
|
1241 | 0 | for (int j = j0; j < j1; j++, k++, m += nDim) |
1242 | 0 | if (m_bitMask.IsValid(k)) |
1243 | 0 | data[m] = 0; |
1244 | 0 | } |
1245 | |
|
1246 | 0 | *ppByte = ptr; |
1247 | 0 | nBytesRemainingInOut = nBytesRemaining; |
1248 | 0 | return true; |
1249 | 0 | } |
1250 | | |
1251 | 0 | else if (comprFlag == 0) // read z's binary uncompressed |
1252 | 0 | { |
1253 | 0 | const T* srcPtr = (const T*)ptr; |
1254 | 0 | int cnt = 0; |
1255 | |
|
1256 | 0 | for (int i = i0; i < i1; i++) |
1257 | 0 | { |
1258 | 0 | int k = i * nCols + j0; |
1259 | 0 | int m = k * nDim + iDim; |
1260 | |
|
1261 | 0 | for (int j = j0; j < j1; j++, k++, m += nDim) |
1262 | 0 | if (m_bitMask.IsValid(k)) |
1263 | 0 | { |
1264 | 0 | if (nBytesRemaining < sizeof(T)) |
1265 | 0 | return false; |
1266 | | |
1267 | 0 | data[m] = *srcPtr++; |
1268 | 0 | nBytesRemaining -= sizeof(T); |
1269 | |
|
1270 | 0 | cnt++; |
1271 | 0 | } |
1272 | 0 | } |
1273 | | |
1274 | 0 | ptr += cnt * sizeof(T); |
1275 | 0 | } |
1276 | 0 | else |
1277 | 0 | { |
1278 | | // read z's as int arr bit stuffed |
1279 | 0 | DataType dtUsed = GetDataTypeUsed(bits67); |
1280 | 0 | if( dtUsed == DT_Undefined ) |
1281 | 0 | return false; |
1282 | 0 | size_t n = GetDataTypeSize(dtUsed); |
1283 | 0 | if (nBytesRemaining < n) |
1284 | 0 | return false; |
1285 | | |
1286 | 0 | double offset = ReadVariableDataType(&ptr, dtUsed); |
1287 | 0 | nBytesRemaining -= n; |
1288 | |
|
1289 | 0 | if (comprFlag == 3) // entire tile is constant zMin (all the valid pixels) |
1290 | 0 | { |
1291 | 0 | for (int i = i0; i < i1; i++) |
1292 | 0 | { |
1293 | 0 | int k = i * nCols + j0; |
1294 | 0 | int m = k * nDim + iDim; |
1295 | |
|
1296 | 0 | for (int j = j0; j < j1; j++, k++, m += nDim) |
1297 | 0 | if (m_bitMask.IsValid(k)) |
1298 | 0 | data[m] = (T)offset; |
1299 | 0 | } |
1300 | 0 | } |
1301 | 0 | else |
1302 | 0 | { |
1303 | 0 | size_t maxElementCount = (i1 - i0) * (j1 - j0); |
1304 | 0 | if (!m_bitStuffer2.Decode(&ptr, nBytesRemaining, bufferVec, maxElementCount, hd.version)) |
1305 | 0 | return false; |
1306 | | |
1307 | 0 | double invScale = 2 * hd.maxZError; // for int types this is int |
1308 | 0 | double zMax = (hd.version >= 4 && nDim > 1) ? m_zMaxVec[iDim] : hd.zMax; |
1309 | 0 | const unsigned int* srcPtr = bufferVec.data(); |
1310 | |
|
1311 | 0 | if (bufferVec.size() == maxElementCount) // all valid |
1312 | 0 | { |
1313 | 0 | for (int i = i0; i < i1; i++) |
1314 | 0 | { |
1315 | 0 | int k = i * nCols + j0; |
1316 | 0 | int m = k * nDim + iDim; |
1317 | |
|
1318 | 0 | for (int j = j0; j < j1; j++, k++, m += nDim) |
1319 | 0 | { |
1320 | 0 | double z = offset + *srcPtr++ * invScale; |
1321 | 0 | data[m] = (T)std::min(z, zMax); // make sure we stay in the orig range |
1322 | 0 | } |
1323 | 0 | } |
1324 | 0 | } |
1325 | 0 | else // not all valid |
1326 | 0 | { |
1327 | | #ifndef GDAL_COMPILATION |
1328 | | if (hd.version > 2) |
1329 | | { |
1330 | | for (int i = i0; i < i1; i++) |
1331 | | { |
1332 | | int k = i * nCols + j0; |
1333 | | int m = k * nDim + iDim; |
1334 | | |
1335 | | for (int j = j0; j < j1; j++, k++, m += nDim) |
1336 | | if (m_bitMask.IsValid(k)) |
1337 | | { |
1338 | | double z = offset + *srcPtr++ * invScale; |
1339 | | data[m] = (T)std::min(z, zMax); // make sure we stay in the orig range |
1340 | | } |
1341 | | } |
1342 | | } |
1343 | | else // fail gracefully in case of corrupted blob for old version <= 2 which had no checksum |
1344 | | #endif |
1345 | 0 | { |
1346 | 0 | size_t bufferVecIdx = 0; |
1347 | |
|
1348 | 0 | for (int i = i0; i < i1; i++) |
1349 | 0 | { |
1350 | 0 | int k = i * nCols + j0; |
1351 | 0 | int m = k * nDim + iDim; |
1352 | |
|
1353 | 0 | for (int j = j0; j < j1; j++, k++, m += nDim) |
1354 | 0 | if (m_bitMask.IsValid(k)) |
1355 | 0 | { |
1356 | 0 | if (bufferVecIdx == bufferVec.size()) // fail gracefully in case of corrupted blob for old version <= 2 which had no checksum |
1357 | 0 | return false; |
1358 | | |
1359 | 0 | double z = offset + bufferVec[bufferVecIdx] * invScale; |
1360 | 0 | bufferVecIdx++; |
1361 | 0 | data[m] = (T)std::min(z, zMax); // make sure we stay in the orig range |
1362 | 0 | } |
1363 | 0 | } |
1364 | 0 | } |
1365 | 0 | } |
1366 | 0 | } |
1367 | 0 | } |
1368 | | |
1369 | 0 | *ppByte = ptr; |
1370 | 0 | nBytesRemainingInOut = nBytesRemaining; |
1371 | 0 | return true; |
1372 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<signed char>(unsigned char const**, unsigned long&, signed char*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<unsigned char>(unsigned char const**, unsigned long&, unsigned char*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<short>(unsigned char const**, unsigned long&, short*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<unsigned short>(unsigned char const**, unsigned long&, unsigned short*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<int>(unsigned char const**, unsigned long&, int*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<unsigned int>(unsigned char const**, unsigned long&, unsigned int*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<float>(unsigned char const**, unsigned long&, float*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadTile<double>(unsigned char const**, unsigned long&, double*, int, int, int, int, int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&) const |
1373 | | |
1374 | | // -------------------------------------------------------------------------- ; |
1375 | | |
1376 | | template<class T> |
1377 | | int Lerc2::TypeCode(T z, DataType& dtUsed) const |
1378 | 0 | { |
1379 | 0 | Byte b = (Byte)z; |
1380 | 0 | DataType dt = m_headerInfo.dt; |
1381 | 0 | switch (dt) |
1382 | 0 | { |
1383 | 0 | case DT_Short: |
1384 | 0 | { |
1385 | 0 | signed char c = (signed char)z; |
1386 | 0 | int tc = (T)c == z ? 2 : (T)b == z ? 1 : 0; |
1387 | 0 | dtUsed = (DataType)(dt - tc); |
1388 | 0 | return tc; |
1389 | 0 | } |
1390 | 0 | case DT_UShort: |
1391 | 0 | { |
1392 | 0 | int tc = (T)b == z ? 1 : 0; |
1393 | 0 | dtUsed = (DataType)(dt - 2 * tc); |
1394 | 0 | return tc; |
1395 | 0 | } |
1396 | 0 | case DT_Int: |
1397 | 0 | { |
1398 | 0 | short s = (short)z; |
1399 | 0 | unsigned short us = (unsigned short)z; |
1400 | 0 | int tc = (T)b == z ? 3 : (T)s == z ? 2 : (T)us == z ? 1 : 0; |
1401 | 0 | dtUsed = (DataType)(dt - tc); |
1402 | 0 | return tc; |
1403 | 0 | } |
1404 | 0 | case DT_UInt: |
1405 | 0 | { |
1406 | 0 | unsigned short us = (unsigned short)z; |
1407 | 0 | int tc = (T)b == z ? 2 : (T)us == z ? 1 : 0; |
1408 | 0 | dtUsed = (DataType)(dt - 2 * tc); |
1409 | 0 | return tc; |
1410 | 0 | } |
1411 | 0 | case DT_Float: |
1412 | 0 | { |
1413 | 0 | short s = (short)z; |
1414 | 0 | int tc = (T)b == z ? 2 : (T)s == z ? 1 : 0; |
1415 | 0 | dtUsed = tc == 0 ? dt : (tc == 1 ? DT_Short : DT_Byte); |
1416 | 0 | return tc; |
1417 | 0 | } |
1418 | 0 | case DT_Double: |
1419 | 0 | { |
1420 | 0 | short s = (short)z; |
1421 | 0 | int l = (int)z; |
1422 | 0 | float f = (float)z; |
1423 | 0 | int tc = (T)s == z ? 3 : (T)l == z ? 2 : (T)f == z ? 1 : 0; |
1424 | 0 | dtUsed = tc == 0 ? dt : (DataType)(dt - 2 * tc + 1); |
1425 | 0 | return tc; |
1426 | 0 | } |
1427 | 0 | default: |
1428 | 0 | { |
1429 | 0 | dtUsed = dt; |
1430 | 0 | return 0; |
1431 | 0 | } |
1432 | 0 | } |
1433 | 0 | } Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<signed char>(signed char, GDAL_LercNS::Lerc2::DataType&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<unsigned char>(unsigned char, GDAL_LercNS::Lerc2::DataType&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<short>(short, GDAL_LercNS::Lerc2::DataType&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<unsigned short>(unsigned short, GDAL_LercNS::Lerc2::DataType&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<int>(int, GDAL_LercNS::Lerc2::DataType&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<unsigned int>(unsigned int, GDAL_LercNS::Lerc2::DataType&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<float>(float, GDAL_LercNS::Lerc2::DataType&) const Unexecuted instantiation: int GDAL_LercNS::Lerc2::TypeCode<double>(double, GDAL_LercNS::Lerc2::DataType&) const |
1434 | | |
1435 | | // -------------------------------------------------------------------------- ; |
1436 | | |
1437 | | inline Lerc2::DataType Lerc2::ValidateDataType(int dt) |
1438 | 0 | { |
1439 | 0 | if( dt >= DT_Char && dt <= DT_Double ) |
1440 | 0 | return static_cast<DataType>(dt); |
1441 | 0 | return DT_Undefined; |
1442 | 0 | } |
1443 | | |
1444 | | // -------------------------------------------------------------------------- ; |
1445 | | |
1446 | | inline |
1447 | | Lerc2::DataType Lerc2::GetDataTypeUsed(int tc) const |
1448 | 0 | { |
1449 | 0 | DataType dt = m_headerInfo.dt; |
1450 | 0 | switch (dt) |
1451 | 0 | { |
1452 | 0 | case DT_Short: |
1453 | 0 | case DT_Int: return ValidateDataType(dt - tc); |
1454 | 0 | case DT_UShort: |
1455 | 0 | case DT_UInt: return ValidateDataType(dt - 2 * tc); |
1456 | 0 | case DT_Float: return tc == 0 ? dt : (tc == 1 ? DT_Short : DT_Byte); |
1457 | 0 | case DT_Double: return tc == 0 ? dt : ValidateDataType(dt - 2 * tc + 1); |
1458 | 0 | default: |
1459 | 0 | return dt; |
1460 | 0 | } |
1461 | 0 | } |
1462 | | |
1463 | | // -------------------------------------------------------------------------- ; |
1464 | | |
1465 | | inline |
1466 | | bool Lerc2::WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed) |
1467 | 0 | { |
1468 | 0 | Byte* ptr = *ppByte; |
1469 | |
|
1470 | 0 | switch (dtUsed) |
1471 | 0 | { |
1472 | 0 | case DT_Char: |
1473 | 0 | { |
1474 | 0 | *((signed char*)ptr) = (signed char)z; |
1475 | 0 | ptr++; |
1476 | 0 | break; |
1477 | 0 | } |
1478 | 0 | case DT_Byte: |
1479 | 0 | { |
1480 | 0 | *((Byte*)ptr) = (Byte)z; |
1481 | 0 | ptr++; |
1482 | 0 | break; |
1483 | 0 | } |
1484 | 0 | case DT_Short: |
1485 | 0 | { |
1486 | 0 | short s = (short)z; |
1487 | 0 | memcpy(ptr, &s, sizeof(short)); |
1488 | 0 | ptr += 2; |
1489 | 0 | break; |
1490 | 0 | } |
1491 | 0 | case DT_UShort: |
1492 | 0 | { |
1493 | 0 | unsigned short us = (unsigned short)z; |
1494 | 0 | memcpy(ptr, &us, sizeof(unsigned short)); |
1495 | 0 | ptr += 2; |
1496 | 0 | break; |
1497 | 0 | } |
1498 | 0 | case DT_Int: |
1499 | 0 | { |
1500 | 0 | int i = (int)z; |
1501 | 0 | memcpy(ptr, &i, sizeof(int)); |
1502 | 0 | ptr += 4; |
1503 | 0 | break; |
1504 | 0 | } |
1505 | 0 | case DT_UInt: |
1506 | 0 | { |
1507 | 0 | unsigned int n = (unsigned int)z; |
1508 | 0 | memcpy(ptr, &n, sizeof(unsigned int)); |
1509 | 0 | ptr += 4; |
1510 | 0 | break; |
1511 | 0 | } |
1512 | 0 | case DT_Float: |
1513 | 0 | { |
1514 | 0 | float f = (float)z; |
1515 | 0 | memcpy(ptr, &f, sizeof(float)); |
1516 | 0 | ptr += 4; |
1517 | 0 | break; |
1518 | 0 | } |
1519 | 0 | case DT_Double: |
1520 | 0 | { |
1521 | 0 | memcpy(ptr, &z, sizeof(double)); |
1522 | 0 | ptr += 8; |
1523 | 0 | break; |
1524 | 0 | } |
1525 | | |
1526 | 0 | default: |
1527 | 0 | return false; |
1528 | 0 | } |
1529 | | |
1530 | 0 | *ppByte = ptr; |
1531 | 0 | return true; |
1532 | 0 | } |
1533 | | |
1534 | | // -------------------------------------------------------------------------- ; |
1535 | | |
1536 | | inline |
1537 | | double Lerc2::ReadVariableDataType(const Byte** ppByte, DataType dtUsed) |
1538 | 0 | { |
1539 | 0 | const Byte* ptr = *ppByte; |
1540 | |
|
1541 | 0 | switch (dtUsed) |
1542 | 0 | { |
1543 | 0 | case DT_Char: |
1544 | 0 | { |
1545 | 0 | signed char c = *((signed char*)ptr); |
1546 | 0 | *ppByte = ptr + 1; |
1547 | 0 | return c; |
1548 | 0 | } |
1549 | 0 | case DT_Byte: |
1550 | 0 | { |
1551 | 0 | Byte b = *((Byte*)ptr); |
1552 | 0 | *ppByte = ptr + 1; |
1553 | 0 | return b; |
1554 | 0 | } |
1555 | 0 | case DT_Short: |
1556 | 0 | { |
1557 | 0 | short s; |
1558 | 0 | memcpy(&s, ptr, sizeof(short)); |
1559 | 0 | *ppByte = ptr + 2; |
1560 | 0 | return s; |
1561 | 0 | } |
1562 | 0 | case DT_UShort: |
1563 | 0 | { |
1564 | 0 | unsigned short us; |
1565 | 0 | memcpy(&us, ptr, sizeof(unsigned short)); |
1566 | 0 | *ppByte = ptr + 2; |
1567 | 0 | return us; |
1568 | 0 | } |
1569 | 0 | case DT_Int: |
1570 | 0 | { |
1571 | 0 | int i; |
1572 | 0 | memcpy(&i, ptr, sizeof(int)); |
1573 | 0 | *ppByte = ptr + 4; |
1574 | 0 | return i; |
1575 | 0 | } |
1576 | 0 | case DT_UInt: |
1577 | 0 | { |
1578 | 0 | unsigned int n; |
1579 | 0 | memcpy(&n, ptr, sizeof(unsigned int)); |
1580 | 0 | *ppByte = ptr + 4; |
1581 | 0 | return n; |
1582 | 0 | } |
1583 | 0 | case DT_Float: |
1584 | 0 | { |
1585 | 0 | float f; |
1586 | 0 | memcpy(&f, ptr, sizeof(float)); |
1587 | 0 | *ppByte = ptr + 4; |
1588 | 0 | return f; |
1589 | 0 | } |
1590 | 0 | case DT_Double: |
1591 | 0 | { |
1592 | 0 | double d; |
1593 | 0 | memcpy(&d, ptr, sizeof(double)); |
1594 | 0 | *ppByte = ptr + 8; |
1595 | 0 | return d; |
1596 | 0 | } |
1597 | 0 | default: |
1598 | 0 | return 0; |
1599 | 0 | } |
1600 | 0 | } |
1601 | | |
1602 | | // -------------------------------------------------------------------------- ; |
1603 | | |
1604 | | template<class T> |
1605 | | Lerc2::DataType Lerc2::GetDataType(T z) const |
1606 | 0 | { |
1607 | 0 | const std::type_info& ti = typeid(z); |
1608 | |
|
1609 | 0 | if (ti == typeid(signed char)) return DT_Char; |
1610 | 0 | else if (ti == typeid(Byte)) return DT_Byte; |
1611 | 0 | else if (ti == typeid(short)) return DT_Short; |
1612 | 0 | else if (ti == typeid(unsigned short)) return DT_UShort; |
1613 | 0 | else if (ti == typeid(int ) && sizeof(int ) == 4) return DT_Int; |
1614 | 0 | else if (ti == typeid(long) && sizeof(long) == 4) return DT_Int; |
1615 | 0 | else if (ti == typeid(unsigned int ) && sizeof(unsigned int ) == 4) return DT_UInt; |
1616 | 0 | else if (ti == typeid(unsigned long) && sizeof(unsigned long) == 4) return DT_UInt; |
1617 | 0 | else if (ti == typeid(float)) return DT_Float; |
1618 | 0 | else if (ti == typeid(double)) return DT_Double; |
1619 | 0 | else |
1620 | 0 | return DT_Undefined; |
1621 | 0 | } Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<signed char>(signed char) const Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<unsigned char>(unsigned char) const Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<short>(short) const Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<unsigned short>(unsigned short) const Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<int>(int) const Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<unsigned int>(unsigned int) const Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<float>(float) const Unexecuted instantiation: GDAL_LercNS::Lerc2::DataType GDAL_LercNS::Lerc2::GetDataType<double>(double) const |
1622 | | |
1623 | | // -------------------------------------------------------------------------- ; |
1624 | | |
1625 | | inline |
1626 | | unsigned int Lerc2::GetMaxValToQuantize(DataType dt) |
1627 | 0 | { |
1628 | 0 | switch (dt) |
1629 | 0 | { |
1630 | 0 | case DT_Char: |
1631 | 0 | case DT_Byte: //return (1 << 7) - 1; // disabled: allow LUT mode for 8 bit segmented |
1632 | 0 | case DT_Short: |
1633 | 0 | case DT_UShort: return (1 << 15) - 1; |
1634 | | |
1635 | 0 | case DT_Int: |
1636 | 0 | case DT_UInt: |
1637 | 0 | case DT_Float: |
1638 | 0 | case DT_Double: return (1 << 30) - 1; |
1639 | | |
1640 | 0 | default: |
1641 | 0 | return 0; |
1642 | 0 | } |
1643 | 0 | } |
1644 | | |
1645 | | // -------------------------------------------------------------------------- ; |
1646 | | |
1647 | | inline |
1648 | | unsigned int Lerc2::GetDataTypeSize(DataType dt) |
1649 | 0 | { |
1650 | 0 | switch (dt) |
1651 | 0 | { |
1652 | 0 | case DT_Char: |
1653 | 0 | case DT_Byte: return 1; |
1654 | 0 | case DT_Short: |
1655 | 0 | case DT_UShort: return 2; |
1656 | 0 | case DT_Int: |
1657 | 0 | case DT_UInt: |
1658 | 0 | case DT_Float: return 4; |
1659 | 0 | case DT_Double: return 8; |
1660 | | |
1661 | 0 | default: |
1662 | 0 | return 0; |
1663 | 0 | } |
1664 | 0 | } |
1665 | | |
1666 | | // -------------------------------------------------------------------------- ; |
1667 | | |
1668 | | template<class T> |
1669 | | void Lerc2::ComputeHuffmanCodes(const T* data, int& numBytes, ImageEncodeMode& imageEncodeMode, std::vector<std::pair<unsigned short, unsigned int> >& codes) const |
1670 | 0 | { |
1671 | 0 | std::vector<int> histo, deltaHisto; |
1672 | 0 | ComputeHistoForHuffman(data, histo, deltaHisto); |
1673 | |
|
1674 | 0 | int nBytes0 = 0, nBytes1 = 0; |
1675 | 0 | double avgBpp0 = 0, avgBpp1 = 0; |
1676 | 0 | Huffman huffman0, huffman1; |
1677 | |
|
1678 | 0 | if (m_headerInfo.version >= 4) |
1679 | 0 | { |
1680 | 0 | if (!huffman0.ComputeCodes(histo) || !huffman0.ComputeCompressedSize(histo, nBytes0, avgBpp0)) |
1681 | 0 | nBytes0 = 0; |
1682 | 0 | } |
1683 | |
|
1684 | 0 | if (!huffman1.ComputeCodes(deltaHisto) || !huffman1.ComputeCompressedSize(deltaHisto, nBytes1, avgBpp1)) |
1685 | 0 | nBytes1 = 0; |
1686 | |
|
1687 | 0 | if (nBytes0 > 0 && nBytes1 > 0) // regular case, pick the better of the two |
1688 | 0 | { |
1689 | 0 | imageEncodeMode = (nBytes0 <= nBytes1) ? IEM_Huffman : IEM_DeltaHuffman; |
1690 | 0 | codes = (nBytes0 <= nBytes1) ? huffman0.GetCodes() : huffman1.GetCodes(); |
1691 | 0 | numBytes = (std::min)(nBytes0, nBytes1); |
1692 | 0 | } |
1693 | 0 | else if (nBytes0 == 0 && nBytes1 == 0) // rare case huffman cannot handle, fall back to tiling |
1694 | 0 | { |
1695 | 0 | imageEncodeMode = IEM_Tiling; |
1696 | 0 | codes.resize(0); |
1697 | 0 | numBytes = 0; |
1698 | 0 | } |
1699 | 0 | else // rare also, pick the valid one, the other is 0 |
1700 | 0 | { |
1701 | 0 | imageEncodeMode = (nBytes0 > nBytes1) ? IEM_Huffman : IEM_DeltaHuffman; |
1702 | 0 | codes = (nBytes0 > nBytes1) ? huffman0.GetCodes() : huffman1.GetCodes(); |
1703 | 0 | numBytes = (std::max)(nBytes0, nBytes1); |
1704 | 0 | } |
1705 | 0 | } Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<signed char>(signed char const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<unsigned char>(unsigned char const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<short>(short const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<unsigned short>(unsigned short const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<int>(int const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<unsigned int>(unsigned int const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<float>(float const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHuffmanCodes<double>(double const*, int&, GDAL_LercNS::Lerc2::ImageEncodeMode&, std::__1::vector<std::__1::pair<unsigned short, unsigned int>, std::__1::allocator<std::__1::pair<unsigned short, unsigned int> > >&) const |
1706 | | |
1707 | | // -------------------------------------------------------------------------- ; |
1708 | | |
1709 | | template<class T> |
1710 | | void Lerc2::ComputeHistoForHuffman(const T* data, std::vector<int>& histo, std::vector<int>& deltaHisto) const |
1711 | 0 | { |
1712 | 0 | histo.resize(256); |
1713 | 0 | deltaHisto.resize(256); |
1714 | |
|
1715 | 0 | memset(&histo[0], 0, histo.size() * sizeof(int)); |
1716 | 0 | memset(&deltaHisto[0], 0, deltaHisto.size() * sizeof(int)); |
1717 | |
|
1718 | 0 | int offset = (m_headerInfo.dt == DT_Char) ? 128 : 0; |
1719 | 0 | int height = m_headerInfo.nRows; |
1720 | 0 | int width = m_headerInfo.nCols; |
1721 | 0 | int nDim = m_headerInfo.nDim; |
1722 | |
|
1723 | 0 | if (m_headerInfo.numValidPixel == width * height) // all valid |
1724 | 0 | { |
1725 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
1726 | 0 | { |
1727 | 0 | T prevVal = 0; |
1728 | 0 | for (int m = iDim, i = 0; i < height; i++) |
1729 | 0 | for (int j = 0; j < width; j++, m += nDim) |
1730 | 0 | { |
1731 | 0 | T val = data[m]; |
1732 | 0 | T delta = val; |
1733 | |
|
1734 | 0 | if (j > 0) |
1735 | 0 | delta -= prevVal; // use overflow |
1736 | 0 | else if (i > 0) |
1737 | 0 | delta -= data[m - width * nDim]; |
1738 | 0 | else |
1739 | 0 | delta -= prevVal; |
1740 | |
|
1741 | 0 | prevVal = val; |
1742 | |
|
1743 | 0 | histo[offset + (int)val]++; |
1744 | 0 | deltaHisto[offset + (int)delta]++; |
1745 | 0 | } |
1746 | 0 | } |
1747 | 0 | } |
1748 | 0 | else // not all valid |
1749 | 0 | { |
1750 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
1751 | 0 | { |
1752 | 0 | T prevVal = 0; |
1753 | 0 | for (int k = 0, m = iDim, i = 0; i < height; i++) |
1754 | 0 | for (int j = 0; j < width; j++, k++, m += nDim) |
1755 | 0 | if (m_bitMask.IsValid(k)) |
1756 | 0 | { |
1757 | 0 | T val = data[m]; |
1758 | 0 | T delta = val; |
1759 | |
|
1760 | 0 | if (j > 0 && m_bitMask.IsValid(k - 1)) |
1761 | 0 | { |
1762 | 0 | delta -= prevVal; // use overflow |
1763 | 0 | } |
1764 | 0 | else if (i > 0 && m_bitMask.IsValid(k - width)) |
1765 | 0 | { |
1766 | 0 | delta -= data[m - width * nDim]; |
1767 | 0 | } |
1768 | 0 | else |
1769 | 0 | delta -= prevVal; |
1770 | |
|
1771 | 0 | prevVal = val; |
1772 | |
|
1773 | 0 | histo[offset + (int)val]++; |
1774 | 0 | deltaHisto[offset + (int)delta]++; |
1775 | 0 | } |
1776 | 0 | } |
1777 | 0 | } |
1778 | 0 | } Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<signed char>(signed char const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<unsigned char>(unsigned char const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<short>(short const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<unsigned short>(unsigned short const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<int>(int const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<unsigned int>(unsigned int const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<float>(float const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const Unexecuted instantiation: void GDAL_LercNS::Lerc2::ComputeHistoForHuffman<double>(double const*, std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<int, std::__1::allocator<int> >&) const |
1779 | | |
1780 | | // -------------------------------------------------------------------------- ; |
1781 | | |
1782 | | template<class T> |
1783 | | bool Lerc2::EncodeHuffman(const T* data, Byte** ppByte) const |
1784 | 0 | { |
1785 | 0 | if (!data || !ppByte) |
1786 | 0 | return false; |
1787 | | |
1788 | 0 | Huffman huffman; |
1789 | 0 | if (!huffman.SetCodes(m_huffmanCodes) || !huffman.WriteCodeTable(ppByte, m_headerInfo.version)) // header and code table |
1790 | 0 | return false; |
1791 | | |
1792 | 0 | int offset = (m_headerInfo.dt == DT_Char) ? 128 : 0; |
1793 | 0 | int height = m_headerInfo.nRows; |
1794 | 0 | int width = m_headerInfo.nCols; |
1795 | 0 | int nDim = m_headerInfo.nDim; |
1796 | |
|
1797 | 0 | unsigned int* arr = (unsigned int*)(*ppByte); |
1798 | 0 | unsigned int* dstPtr = arr; |
1799 | 0 | int bitPos = 0; |
1800 | |
|
1801 | 0 | if (m_imageEncodeMode == IEM_DeltaHuffman) |
1802 | 0 | { |
1803 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
1804 | 0 | { |
1805 | 0 | T prevVal = 0; |
1806 | 0 | for (int k = 0, m = iDim, i = 0; i < height; i++) |
1807 | 0 | for (int j = 0; j < width; j++, k++, m += nDim) |
1808 | 0 | if (m_bitMask.IsValid(k)) |
1809 | 0 | { |
1810 | 0 | T val = data[m]; |
1811 | 0 | T delta = val; |
1812 | |
|
1813 | 0 | if (j > 0 && m_bitMask.IsValid(k - 1)) |
1814 | 0 | { |
1815 | 0 | delta -= prevVal; // use overflow |
1816 | 0 | } |
1817 | 0 | else if (i > 0 && m_bitMask.IsValid(k - width)) |
1818 | 0 | { |
1819 | 0 | delta -= data[m - width * nDim]; |
1820 | 0 | } |
1821 | 0 | else |
1822 | 0 | delta -= prevVal; |
1823 | |
|
1824 | 0 | prevVal = val; |
1825 | | |
1826 | | // bit stuff the huffman code for this delta |
1827 | 0 | int kBin = offset + (int)delta; |
1828 | 0 | int len = m_huffmanCodes[kBin].first; |
1829 | 0 | if (len <= 0) |
1830 | 0 | return false; |
1831 | | |
1832 | 0 | unsigned int code = m_huffmanCodes[kBin].second; |
1833 | |
|
1834 | 0 | if (32 - bitPos >= len) |
1835 | 0 | { |
1836 | 0 | if (bitPos == 0) |
1837 | 0 | *dstPtr = 0; |
1838 | |
|
1839 | 0 | *dstPtr |= code << (32 - bitPos - len); |
1840 | 0 | bitPos += len; |
1841 | 0 | if (bitPos == 32) |
1842 | 0 | { |
1843 | 0 | bitPos = 0; |
1844 | 0 | dstPtr++; |
1845 | 0 | } |
1846 | 0 | } |
1847 | 0 | else |
1848 | 0 | { |
1849 | 0 | bitPos += len - 32; |
1850 | 0 | *dstPtr++ |= code >> bitPos; |
1851 | 0 | *dstPtr = code << (32 - bitPos); |
1852 | 0 | } |
1853 | 0 | } |
1854 | 0 | } |
1855 | 0 | } |
1856 | | |
1857 | 0 | else if (m_imageEncodeMode == IEM_Huffman) |
1858 | 0 | { |
1859 | 0 | for (int k = 0, m0 = 0, i = 0; i < height; i++) |
1860 | 0 | for (int j = 0; j < width; j++, k++, m0 += nDim) |
1861 | 0 | if (m_bitMask.IsValid(k)) |
1862 | 0 | for (int m = 0; m < nDim; m++) |
1863 | 0 | { |
1864 | 0 | T val = data[m0 + m]; |
1865 | | |
1866 | | // bit stuff the huffman code for this val |
1867 | 0 | int kBin = offset + (int)val; |
1868 | 0 | int len = m_huffmanCodes[kBin].first; |
1869 | 0 | if (len <= 0) |
1870 | 0 | return false; |
1871 | | |
1872 | 0 | unsigned int code = m_huffmanCodes[kBin].second; |
1873 | |
|
1874 | 0 | if (32 - bitPos >= len) |
1875 | 0 | { |
1876 | 0 | if (bitPos == 0) |
1877 | 0 | *dstPtr = 0; |
1878 | |
|
1879 | 0 | *dstPtr |= code << (32 - bitPos - len); |
1880 | 0 | bitPos += len; |
1881 | 0 | if (bitPos == 32) |
1882 | 0 | { |
1883 | 0 | bitPos = 0; |
1884 | 0 | dstPtr++; |
1885 | 0 | } |
1886 | 0 | } |
1887 | 0 | else |
1888 | 0 | { |
1889 | 0 | bitPos += len - 32; |
1890 | 0 | *dstPtr++ |= code >> bitPos; |
1891 | 0 | *dstPtr = code << (32 - bitPos); |
1892 | 0 | } |
1893 | 0 | } |
1894 | 0 | } |
1895 | | |
1896 | 0 | else |
1897 | 0 | return false; |
1898 | | |
1899 | 0 | size_t numUInts = dstPtr - arr + (bitPos > 0 ? 1 : 0) + 1; // add one more as the decode LUT can read ahead |
1900 | 0 | *ppByte += numUInts * sizeof(unsigned int); |
1901 | 0 | return true; |
1902 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<signed char>(signed char const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<unsigned char>(unsigned char const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<short>(short const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<unsigned short>(unsigned short const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<int>(int const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<unsigned int>(unsigned int const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<float>(float const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::EncodeHuffman<double>(double const*, unsigned char**) const |
1903 | | |
1904 | | // -------------------------------------------------------------------------- ; |
1905 | | |
1906 | | template<class T> |
1907 | | bool Lerc2::DecodeHuffman(const Byte** ppByte, size_t& nBytesRemainingInOut, T* data) const |
1908 | 0 | { |
1909 | 0 | if (!data || !ppByte || !(*ppByte)) |
1910 | 0 | return false; |
1911 | | |
1912 | 0 | Huffman huffman; |
1913 | 0 | if (!huffman.ReadCodeTable(ppByte, nBytesRemainingInOut, m_headerInfo.version)) // header and code table |
1914 | 0 | return false; |
1915 | | |
1916 | 0 | int numBitsLUT = 0; |
1917 | 0 | if (!huffman.BuildTreeFromCodes(numBitsLUT)) |
1918 | 0 | return false; |
1919 | | |
1920 | 0 | int offset = (m_headerInfo.dt == DT_Char) ? 128 : 0; |
1921 | 0 | int height = m_headerInfo.nRows; |
1922 | 0 | int width = m_headerInfo.nCols; |
1923 | 0 | int nDim = m_headerInfo.nDim; |
1924 | |
|
1925 | 0 | const unsigned int* arr = (const unsigned int*)(*ppByte); |
1926 | 0 | const unsigned int* srcPtr = arr; |
1927 | 0 | int bitPos = 0; |
1928 | 0 | size_t nBytesRemaining = nBytesRemainingInOut; |
1929 | |
|
1930 | 0 | if (m_headerInfo.numValidPixel == width * height) // all valid |
1931 | 0 | { |
1932 | 0 | if (m_imageEncodeMode == IEM_DeltaHuffman) |
1933 | 0 | { |
1934 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
1935 | 0 | { |
1936 | 0 | T prevVal = 0; |
1937 | 0 | for (int m = iDim, i = 0; i < height; i++) |
1938 | 0 | for (int j = 0; j < width; j++, m += nDim) |
1939 | 0 | { |
1940 | 0 | int val = 0; |
1941 | 0 | if (nBytesRemaining >= 4 * sizeof(unsigned int)) |
1942 | 0 | { |
1943 | 0 | if (!huffman.DecodeOneValue_NoOverrunCheck(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
1944 | 0 | return false; |
1945 | 0 | } |
1946 | 0 | else |
1947 | 0 | { |
1948 | 0 | if (!huffman.DecodeOneValue(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
1949 | 0 | return false; |
1950 | 0 | } |
1951 | | |
1952 | 0 | T delta = (T)(val - offset); |
1953 | |
|
1954 | 0 | if (j > 0) |
1955 | 0 | delta += prevVal; // use overflow |
1956 | 0 | else if (i > 0) |
1957 | 0 | delta += data[m - width * nDim]; |
1958 | 0 | else |
1959 | 0 | delta += prevVal; |
1960 | |
|
1961 | 0 | data[m] = delta; |
1962 | 0 | prevVal = delta; |
1963 | 0 | } |
1964 | 0 | } |
1965 | 0 | } |
1966 | | |
1967 | 0 | else if (m_imageEncodeMode == IEM_Huffman) |
1968 | 0 | { |
1969 | 0 | for (int k = 0, m0 = 0, i = 0; i < height; i++) |
1970 | 0 | for (int j = 0; j < width; j++, k++, m0 += nDim) |
1971 | 0 | for (int m = 0; m < nDim; m++) |
1972 | 0 | { |
1973 | 0 | int val = 0; |
1974 | 0 | if (nBytesRemaining >= 4 * sizeof(unsigned int)) |
1975 | 0 | { |
1976 | 0 | if (!huffman.DecodeOneValue_NoOverrunCheck(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
1977 | 0 | return false; |
1978 | 0 | } |
1979 | 0 | else |
1980 | 0 | { |
1981 | 0 | if (!huffman.DecodeOneValue(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
1982 | 0 | return false; |
1983 | 0 | } |
1984 | | |
1985 | 0 | data[m0 + m] = (T)(val - offset); |
1986 | 0 | } |
1987 | 0 | } |
1988 | | |
1989 | 0 | else |
1990 | 0 | return false; |
1991 | 0 | } |
1992 | | |
1993 | 0 | else // not all valid |
1994 | 0 | { |
1995 | 0 | if (m_imageEncodeMode == IEM_DeltaHuffman) |
1996 | 0 | { |
1997 | 0 | for (int iDim = 0; iDim < nDim; iDim++) |
1998 | 0 | { |
1999 | 0 | T prevVal = 0; |
2000 | 0 | for (int k = 0, m = iDim, i = 0; i < height; i++) |
2001 | 0 | for (int j = 0; j < width; j++, k++, m += nDim) |
2002 | 0 | if (m_bitMask.IsValid(k)) |
2003 | 0 | { |
2004 | 0 | int val = 0; |
2005 | 0 | if (nBytesRemaining >= 4 * sizeof(unsigned int)) |
2006 | 0 | { |
2007 | 0 | if (!huffman.DecodeOneValue_NoOverrunCheck(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
2008 | 0 | return false; |
2009 | 0 | } |
2010 | 0 | else |
2011 | 0 | { |
2012 | 0 | if (!huffman.DecodeOneValue(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
2013 | 0 | return false; |
2014 | 0 | } |
2015 | | |
2016 | 0 | T delta = (T)(val - offset); |
2017 | |
|
2018 | 0 | if (j > 0 && m_bitMask.IsValid(k - 1)) |
2019 | 0 | { |
2020 | 0 | delta += prevVal; // use overflow |
2021 | 0 | } |
2022 | 0 | else if (i > 0 && m_bitMask.IsValid(k - width)) |
2023 | 0 | { |
2024 | 0 | delta += data[m - width * nDim]; |
2025 | 0 | } |
2026 | 0 | else |
2027 | 0 | delta += prevVal; |
2028 | |
|
2029 | 0 | data[m] = delta; |
2030 | 0 | prevVal = delta; |
2031 | 0 | } |
2032 | 0 | } |
2033 | 0 | } |
2034 | | |
2035 | 0 | else if (m_imageEncodeMode == IEM_Huffman) |
2036 | 0 | { |
2037 | 0 | for (int k = 0, m0 = 0, i = 0; i < height; i++) |
2038 | 0 | for (int j = 0; j < width; j++, k++, m0 += nDim) |
2039 | 0 | if (m_bitMask.IsValid(k)) |
2040 | 0 | for (int m = 0; m < nDim; m++) |
2041 | 0 | { |
2042 | 0 | int val = 0; |
2043 | 0 | if (nBytesRemaining >= 4 * sizeof(unsigned int)) |
2044 | 0 | { |
2045 | 0 | if (!huffman.DecodeOneValue_NoOverrunCheck(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
2046 | 0 | return false; |
2047 | 0 | } |
2048 | 0 | else |
2049 | 0 | { |
2050 | 0 | if (!huffman.DecodeOneValue(&srcPtr, nBytesRemaining, bitPos, numBitsLUT, val)) |
2051 | 0 | return false; |
2052 | 0 | } |
2053 | | |
2054 | 0 | data[m0 + m] = (T)(val - offset); |
2055 | 0 | } |
2056 | 0 | } |
2057 | | |
2058 | 0 | else |
2059 | 0 | return false; |
2060 | 0 | } |
2061 | | |
2062 | 0 | size_t numUInts = srcPtr - arr + (bitPos > 0 ? 1 : 0) + 1; // add one more as the decode LUT can read ahead |
2063 | 0 | size_t len = numUInts * sizeof(unsigned int); |
2064 | |
|
2065 | 0 | if (nBytesRemainingInOut < len) |
2066 | 0 | return false; |
2067 | | |
2068 | 0 | *ppByte += len; |
2069 | 0 | nBytesRemainingInOut -= len; |
2070 | 0 | return true; |
2071 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<signed char>(unsigned char const**, unsigned long&, signed char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<unsigned char>(unsigned char const**, unsigned long&, unsigned char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<short>(unsigned char const**, unsigned long&, short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<unsigned short>(unsigned char const**, unsigned long&, unsigned short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<int>(unsigned char const**, unsigned long&, int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<unsigned int>(unsigned char const**, unsigned long&, unsigned int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<float>(unsigned char const**, unsigned long&, float*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::DecodeHuffman<double>(unsigned char const**, unsigned long&, double*) const |
2072 | | |
2073 | | // -------------------------------------------------------------------------- ; |
2074 | | |
2075 | | template<class T> |
2076 | | bool Lerc2::WriteMinMaxRanges(const T* /*data*/, Byte** ppByte) const |
2077 | 0 | { |
2078 | 0 | if (!ppByte || !(*ppByte)) |
2079 | 0 | return false; |
2080 | | |
2081 | | //printf("write min / max = %f %f\n", m_zMinVec[0], m_zMaxVec[0]); |
2082 | | |
2083 | 0 | int nDim = m_headerInfo.nDim; |
2084 | 0 | if (/* nDim < 2 || */ (int)m_zMinVec.size() != nDim || (int)m_zMaxVec.size() != nDim) |
2085 | 0 | return false; |
2086 | | |
2087 | 0 | std::vector<T> zVec(nDim); |
2088 | 0 | size_t len = nDim * sizeof(T); |
2089 | |
|
2090 | 0 | for (int i = 0; i < nDim; i++) |
2091 | 0 | zVec[i] = (T)m_zMinVec[i]; |
2092 | |
|
2093 | 0 | memcpy(*ppByte, &zVec[0], len); |
2094 | 0 | (*ppByte) += len; |
2095 | |
|
2096 | 0 | for (int i = 0; i < nDim; i++) |
2097 | 0 | zVec[i] = (T)m_zMaxVec[i]; |
2098 | |
|
2099 | 0 | memcpy(*ppByte, &zVec[0], len); |
2100 | 0 | (*ppByte) += len; |
2101 | |
|
2102 | 0 | return true; |
2103 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<signed char>(signed char const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<unsigned char>(unsigned char const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<short>(short const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<unsigned short>(unsigned short const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<int>(int const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<unsigned int>(unsigned int const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<float>(float const*, unsigned char**) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::WriteMinMaxRanges<double>(double const*, unsigned char**) const |
2104 | | |
2105 | | // -------------------------------------------------------------------------- ; |
2106 | | |
2107 | | template<class T> |
2108 | | bool Lerc2::ReadMinMaxRanges(const Byte** ppByte, size_t& nBytesRemaining, const T* /*data*/) |
2109 | 0 | { |
2110 | 0 | if (!ppByte || !(*ppByte)) |
2111 | 0 | return false; |
2112 | | |
2113 | 0 | int nDim = m_headerInfo.nDim; |
2114 | |
|
2115 | 0 | m_zMinVec.resize(nDim); |
2116 | 0 | m_zMaxVec.resize(nDim); |
2117 | |
|
2118 | 0 | std::vector<T> zVec(nDim); |
2119 | 0 | size_t len = nDim * sizeof(T); |
2120 | |
|
2121 | 0 | if (nBytesRemaining < len || !memcpy(&zVec[0], *ppByte, len)) |
2122 | 0 | return false; |
2123 | | |
2124 | 0 | (*ppByte) += len; |
2125 | 0 | nBytesRemaining -= len; |
2126 | |
|
2127 | 0 | for (int i = 0; i < nDim; i++) |
2128 | 0 | m_zMinVec[i] = zVec[i]; |
2129 | |
|
2130 | 0 | if (nBytesRemaining < len || !memcpy(&zVec[0], *ppByte, len)) |
2131 | 0 | return false; |
2132 | | |
2133 | 0 | (*ppByte) += len; |
2134 | 0 | nBytesRemaining -= len; |
2135 | |
|
2136 | 0 | for (int i = 0; i < nDim; i++) |
2137 | 0 | m_zMaxVec[i] = zVec[i]; |
2138 | | |
2139 | | //printf("read min / max = %f %f\n", m_zMinVec[0], m_zMaxVec[0]); |
2140 | |
|
2141 | 0 | return true; |
2142 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<signed char>(unsigned char const**, unsigned long&, signed char const*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<unsigned char>(unsigned char const**, unsigned long&, unsigned char const*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<short>(unsigned char const**, unsigned long&, short const*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<unsigned short>(unsigned char const**, unsigned long&, unsigned short const*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<int>(unsigned char const**, unsigned long&, int const*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<unsigned int>(unsigned char const**, unsigned long&, unsigned int const*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<float>(unsigned char const**, unsigned long&, float const*) Unexecuted instantiation: bool GDAL_LercNS::Lerc2::ReadMinMaxRanges<double>(unsigned char const**, unsigned long&, double const*) |
2143 | | |
2144 | | // -------------------------------------------------------------------------- ; |
2145 | | |
2146 | | inline |
2147 | | bool Lerc2::CheckMinMaxRanges(bool& minMaxEqual) const |
2148 | 0 | { |
2149 | 0 | int nDim = m_headerInfo.nDim; |
2150 | 0 | if ((int)m_zMinVec.size() != nDim || (int)m_zMaxVec.size() != nDim) |
2151 | 0 | return false; |
2152 | | |
2153 | 0 | minMaxEqual = (0 == memcmp(&m_zMinVec[0], &m_zMaxVec[0], nDim * sizeof(m_zMinVec[0]))); |
2154 | 0 | return true; |
2155 | 0 | } |
2156 | | |
2157 | | // -------------------------------------------------------------------------- ; |
2158 | | |
2159 | | template<class T> |
2160 | | bool Lerc2::FillConstImage(T* data) const |
2161 | 0 | { |
2162 | 0 | if (!data) |
2163 | 0 | return false; |
2164 | | |
2165 | 0 | const HeaderInfo& hd = m_headerInfo; |
2166 | 0 | int nCols = hd.nCols; |
2167 | 0 | int nRows = hd.nRows; |
2168 | 0 | int nDim = hd.nDim; |
2169 | 0 | T z0 = (T)hd.zMin; |
2170 | |
|
2171 | 0 | if (nDim == 1) |
2172 | 0 | { |
2173 | 0 | for (int k = 0, i = 0; i < nRows; i++) |
2174 | 0 | for (int j = 0; j < nCols; j++, k++) |
2175 | 0 | if (m_bitMask.IsValid(k)) |
2176 | 0 | data[k] = z0; |
2177 | 0 | } |
2178 | 0 | else |
2179 | 0 | { |
2180 | 0 | std::vector<T> zBufVec(nDim, z0); |
2181 | |
|
2182 | 0 | if (hd.zMin != hd.zMax) |
2183 | 0 | { |
2184 | 0 | if ((int)m_zMinVec.size() != nDim) |
2185 | 0 | return false; |
2186 | | |
2187 | 0 | for (int m = 0; m < nDim; m++) |
2188 | 0 | zBufVec[m] = (T)m_zMinVec[m]; |
2189 | 0 | } |
2190 | | |
2191 | 0 | int len = nDim * sizeof(T); |
2192 | 0 | for (int k = 0, m = 0, i = 0; i < nRows; i++) |
2193 | 0 | for (int j = 0; j < nCols; j++, k++, m += nDim) |
2194 | 0 | if (m_bitMask.IsValid(k)) |
2195 | 0 | memcpy(&data[m], &zBufVec[0], len); |
2196 | 0 | } |
2197 | | |
2198 | 0 | return true; |
2199 | 0 | } Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<signed char>(signed char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<unsigned char>(unsigned char*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<short>(short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<unsigned short>(unsigned short*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<int>(int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<unsigned int>(unsigned int*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<float>(float*) const Unexecuted instantiation: bool GDAL_LercNS::Lerc2::FillConstImage<double>(double*) const |
2200 | | |
2201 | | // -------------------------------------------------------------------------- ; |
2202 | | |
2203 | | NAMESPACE_LERC_END |
2204 | | #endif |