Coverage Report

Created: 2025-06-13 06:18

/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