Coverage Report

Created: 2025-06-13 06:18

/src/gdal/third_party/LercLib/Lerc.cpp
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
#include "Defines.h"
25
#include "Lerc.h"
26
#include "Lerc2.h"
27
#include <typeinfo>
28
#include <limits>
29
30
#ifdef HAVE_LERC1_DECODE
31
#include "Lerc1Decode/CntZImage.h"
32
#endif
33
34
using namespace std;
35
USING_NAMESPACE_LERC
36
37
// -------------------------------------------------------------------------- ;
38
39
ErrCode Lerc::ComputeCompressedSize(const void* pData, int version, DataType dt, int nDim, int nCols, int nRows, int nBands,
40
  const BitMask* pBitMask, double maxZErr, unsigned int& numBytesNeeded)
41
0
{
42
0
  switch (dt)
43
0
  {
44
0
  case DT_Char:    return ComputeCompressedSizeTempl((const signed char*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
45
0
  case DT_Byte:    return ComputeCompressedSizeTempl((const Byte*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
46
0
  case DT_Short:   return ComputeCompressedSizeTempl((const short*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
47
0
  case DT_UShort:  return ComputeCompressedSizeTempl((const unsigned short*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
48
0
  case DT_Int:     return ComputeCompressedSizeTempl((const int*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
49
0
  case DT_UInt:    return ComputeCompressedSizeTempl((const unsigned int*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
50
0
  case DT_Float:   return ComputeCompressedSizeTempl((const float*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
51
0
  case DT_Double:  return ComputeCompressedSizeTempl((const double*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, numBytesNeeded);
52
53
0
  default:
54
0
    return ErrCode::WrongParam;
55
0
  }
56
0
}
57
58
// -------------------------------------------------------------------------- ;
59
60
ErrCode Lerc::Encode(const void* pData, int version, DataType dt, int nDim, int nCols, int nRows, int nBands,
61
  const BitMask* pBitMask, double maxZErr, Byte* pBuffer, unsigned int numBytesBuffer, unsigned int& numBytesWritten)
62
0
{
63
0
  switch (dt)
64
0
  {
65
0
  case DT_Char:    return EncodeTempl((const signed char*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
66
0
  case DT_Byte:    return EncodeTempl((const Byte*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
67
0
  case DT_Short:   return EncodeTempl((const short*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
68
0
  case DT_UShort:  return EncodeTempl((const unsigned short*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
69
0
  case DT_Int:     return EncodeTempl((const int*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
70
0
  case DT_UInt:    return EncodeTempl((const unsigned int*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
71
0
  case DT_Float:   return EncodeTempl((const float*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
72
0
  case DT_Double:  return EncodeTempl((const double*)pData, version, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pBuffer, numBytesBuffer, numBytesWritten);
73
74
0
  default:
75
0
    return ErrCode::WrongParam;
76
0
  }
77
0
}
78
79
// -------------------------------------------------------------------------- ;
80
81
ErrCode Lerc::GetLercInfo(const Byte* pLercBlob, unsigned int numBytesBlob, struct LercInfo& lercInfo)
82
0
{
83
0
  lercInfo.RawInit();
84
85
  // first try Lerc2
86
0
  struct Lerc2::HeaderInfo lerc2Info;
87
0
  if (Lerc2::GetHeaderInfo(pLercBlob, numBytesBlob, lerc2Info))
88
0
  {
89
0
    lercInfo.version = lerc2Info.version;
90
0
    lercInfo.nDim = lerc2Info.nDim;
91
0
    lercInfo.nCols = lerc2Info.nCols;
92
0
    lercInfo.nRows = lerc2Info.nRows;
93
0
    lercInfo.numValidPixel = lerc2Info.numValidPixel;
94
0
    lercInfo.nBands = 1;
95
0
    lercInfo.blobSize = lerc2Info.blobSize;
96
0
    lercInfo.dt = (DataType)lerc2Info.dt;
97
0
    lercInfo.zMin = lerc2Info.zMin;
98
0
    lercInfo.zMax = lerc2Info.zMax;
99
0
    lercInfo.maxZError = lerc2Info.maxZError;
100
101
0
    if (lercInfo.blobSize > (int)numBytesBlob)    // truncated blob, we won't be able to read this band
102
0
      return ErrCode::BufferTooSmall;
103
104
0
    struct Lerc2::HeaderInfo hdInfo;
105
0
    while (Lerc2::GetHeaderInfo(pLercBlob + lercInfo.blobSize, numBytesBlob - lercInfo.blobSize, hdInfo))
106
0
    {
107
0
      if (hdInfo.nDim != lercInfo.nDim
108
0
       || hdInfo.nCols != lercInfo.nCols
109
0
       || hdInfo.nRows != lercInfo.nRows
110
0
       || hdInfo.numValidPixel != lercInfo.numValidPixel
111
0
       || (int)hdInfo.dt != (int)lercInfo.dt)
112
       //|| hdInfo.maxZError != lercInfo.maxZError)  // with the new bitplane compression, maxZError can vary between bands
113
0
      {
114
0
        return ErrCode::Failed;
115
0
      }
116
117
0
      if (lercInfo.blobSize > std::numeric_limits<int>::max() - hdInfo.blobSize)
118
0
        return ErrCode::Failed;
119
120
0
      lercInfo.blobSize += hdInfo.blobSize;
121
122
0
      if (lercInfo.blobSize > (int)numBytesBlob)    // truncated blob, we won't be able to read this band
123
0
        return ErrCode::BufferTooSmall;
124
125
0
      lercInfo.nBands++;
126
0
      lercInfo.zMin = min(lercInfo.zMin, hdInfo.zMin);
127
0
      lercInfo.zMax = max(lercInfo.zMax, hdInfo.zMax);
128
0
      lercInfo.maxZError = max(lercInfo.maxZError, hdInfo.maxZError);  // with the new bitplane compression, maxZError can vary between bands
129
0
    }
130
131
0
    return ErrCode::Ok;
132
0
  }
133
134
135
#ifdef HAVE_LERC1_DECODE
136
  // only if not Lerc2, try legacy Lerc1
137
  unsigned int numBytesHeaderBand0 = CntZImage::computeNumBytesNeededToReadHeader(false);
138
  unsigned int numBytesHeaderBand1 = CntZImage::computeNumBytesNeededToReadHeader(true);
139
  Byte* pByte = const_cast<Byte*>(pLercBlob);
140
141
  lercInfo.zMin =  FLT_MAX;
142
  lercInfo.zMax = -FLT_MAX;
143
144
  CntZImage cntZImg;
145
  if (numBytesHeaderBand0 <= numBytesBlob && cntZImg.read(&pByte, 1e12, true))    // read just the header
146
  {
147
    size_t nBytesRead = pByte - pLercBlob;
148
    size_t nBytesNeeded = 10 + 4 * sizeof(int) + 1 * sizeof(double);
149
150
    if (nBytesRead < nBytesNeeded)
151
      return ErrCode::Failed;
152
153
    Byte* ptr = const_cast<Byte*>(pLercBlob);
154
    ptr += 10 + 2 * sizeof(int);
155
156
    int height(0), width(0);
157
    memcpy(&height, ptr, sizeof(int));  ptr += sizeof(int);
158
    memcpy(&width,  ptr, sizeof(int));  ptr += sizeof(int);
159
    double maxZErrorInFile(0);
160
    memcpy(&maxZErrorInFile, ptr, sizeof(double));
161
162
    if (height > 20000 || width > 20000)    // guard against bogus numbers; size limitation for old Lerc1
163
      return ErrCode::Failed;
164
165
    lercInfo.nDim = 1;
166
    lercInfo.nCols = width;
167
    lercInfo.nRows = height;
168
    lercInfo.dt = Lerc::DT_Float;
169
    lercInfo.maxZError = maxZErrorInFile;
170
171
    Byte* pByte = const_cast<Byte*>(pLercBlob);
172
    bool onlyZPart = false;
173
174
    while (lercInfo.blobSize + numBytesHeaderBand1 < numBytesBlob)    // means there could be another band
175
    {
176
      if (!cntZImg.read(&pByte, 1e12, false, onlyZPart))
177
        return (lercInfo.nBands > 0) ? ErrCode::Ok : ErrCode::Failed;    // no other band, we are done
178
179
      onlyZPart = true;
180
181
      lercInfo.nBands++;
182
      lercInfo.blobSize = (int)(pByte - pLercBlob);
183
184
      // now that we have decoded it, we can go the extra mile and collect some extra info
185
      int numValidPixels = 0;
186
      float zMin =  FLT_MAX;
187
      float zMax = -FLT_MAX;
188
189
      for (int i = 0; i < height; i++)
190
      {
191
        for (int j = 0; j < width; j++)
192
          if (cntZImg(i, j).cnt > 0)
193
          {
194
            numValidPixels++;
195
            float z = cntZImg(i, j).z;
196
            zMax = max(zMax, z);
197
            zMin = min(zMin, z);
198
          }
199
      }
200
201
      lercInfo.numValidPixel = numValidPixels;
202
      lercInfo.zMin = std::min(lercInfo.zMin, (double)zMin);
203
      lercInfo.zMax = std::max(lercInfo.zMax, (double)zMax);
204
    }
205
206
    return ErrCode::Ok;
207
  }
208
#endif
209
210
0
  return ErrCode::Failed;
211
0
}
212
213
// -------------------------------------------------------------------------- ;
214
215
ErrCode Lerc::Decode(const Byte* pLercBlob, unsigned int numBytesBlob, BitMask* pBitMask,
216
  int nDim, int nCols, int nRows, int nBands, DataType dt, void* pData)
217
0
{
218
0
  switch (dt)
219
0
  {
220
0
  case DT_Char:    return DecodeTempl((signed char*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
221
0
  case DT_Byte:    return DecodeTempl((Byte*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
222
0
  case DT_Short:   return DecodeTempl((short*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
223
0
  case DT_UShort:  return DecodeTempl((unsigned short*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
224
0
  case DT_Int:     return DecodeTempl((int*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
225
0
  case DT_UInt:    return DecodeTempl((unsigned int*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
226
0
  case DT_Float:   return DecodeTempl((float*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
227
0
  case DT_Double:  return DecodeTempl((double*)pData, pLercBlob, numBytesBlob, nDim, nCols, nRows, nBands, pBitMask);
228
229
0
  default:
230
0
    return ErrCode::WrongParam;
231
0
  }
232
0
}
233
234
// -------------------------------------------------------------------------- ;
235
236
ErrCode Lerc::ConvertToDouble(const void* pDataIn, DataType dt, size_t nDataValues, double* pDataOut)
237
0
{
238
0
  switch (dt)
239
0
  {
240
0
  case DT_Char:    return ConvertToDoubleTempl((const signed char*)pDataIn, nDataValues, pDataOut);
241
0
  case DT_Byte:    return ConvertToDoubleTempl((const Byte*)pDataIn, nDataValues, pDataOut);
242
0
  case DT_Short:   return ConvertToDoubleTempl((const short*)pDataIn, nDataValues, pDataOut);
243
0
  case DT_UShort:  return ConvertToDoubleTempl((const unsigned short*)pDataIn, nDataValues, pDataOut);
244
0
  case DT_Int:     return ConvertToDoubleTempl((const int*)pDataIn, nDataValues, pDataOut);
245
0
  case DT_UInt:    return ConvertToDoubleTempl((const unsigned int*)pDataIn, nDataValues, pDataOut);
246
0
  case DT_Float:   return ConvertToDoubleTempl((const float*)pDataIn, nDataValues, pDataOut);
247
  //case DT_Double:  no convert double to double
248
249
0
  default:
250
0
    return ErrCode::WrongParam;
251
0
  }
252
0
}
253
254
// -------------------------------------------------------------------------- ;
255
// -------------------------------------------------------------------------- ;
256
257
template<class T>
258
ErrCode Lerc::ComputeCompressedSizeTempl(const T* pData, int version, int nDim, int nCols, int nRows, int nBands,
259
  const BitMask* pBitMask, double maxZErr, unsigned int& numBytesNeeded)
260
0
{
261
0
  numBytesNeeded = 0;
262
263
0
  if (!pData || nDim <= 0 || nCols <= 0 || nRows <= 0 || nBands <= 0 || maxZErr < 0)
264
0
    return ErrCode::WrongParam;
265
266
0
  if (pBitMask && (pBitMask->GetHeight() != nRows || pBitMask->GetWidth() != nCols))
267
0
    return ErrCode::WrongParam;
268
269
0
  Lerc2 lerc2;
270
0
  if (version >= 0 && !lerc2.SetEncoderToOldVersion(version))
271
0
    return ErrCode::WrongParam;
272
273
0
  bool rv = pBitMask ? lerc2.Set(nDim, nCols, nRows, pBitMask->Bits()) : lerc2.Set(nDim, nCols, nRows);
274
0
  if (!rv)
275
0
    return ErrCode::Failed;
276
277
  // loop over the bands
278
0
  for (int iBand = 0; iBand < nBands; iBand++)
279
0
  {
280
0
    bool encMsk = (iBand == 0);    // store bit mask with first band only
281
0
    const T* arr = pData + nDim * nCols * nRows * iBand;
282
283
0
    ErrCode errCode = CheckForNaN(arr, nDim, nCols, nRows, pBitMask);
284
0
    if (errCode != ErrCode::Ok)
285
0
      return errCode;
286
287
0
    unsigned int nBytes = lerc2.ComputeNumBytesNeededToWrite(arr, maxZErr, encMsk);
288
0
    if (nBytes <= 0)
289
0
      return ErrCode::Failed;
290
291
0
    numBytesNeeded += nBytes;
292
0
  }
293
294
0
  return ErrCode::Ok;
295
0
}
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<signed char>(signed char const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<unsigned char>(unsigned char const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<short>(short const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<unsigned short>(unsigned short const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<int>(int const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<unsigned int>(unsigned int const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<float>(float const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ComputeCompressedSizeTempl<double>(double const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned int&)
296
297
// -------------------------------------------------------------------------- ;
298
299
template<class T>
300
ErrCode Lerc::EncodeTempl(const T* pData, int version, int nDim, int nCols, int nRows, int nBands,
301
  const BitMask* pBitMask, double maxZErr, Byte* pBuffer, unsigned int numBytesBuffer, unsigned int& numBytesWritten)
302
0
{
303
0
  numBytesWritten = 0;
304
305
0
  if (!pData || nDim <= 0 || nCols <= 0 || nRows <= 0 || nBands <= 0 || maxZErr < 0 || !pBuffer || !numBytesBuffer)
306
0
    return ErrCode::WrongParam;
307
308
0
  if (pBitMask && (pBitMask->GetHeight() != nRows || pBitMask->GetWidth() != nCols))
309
0
    return ErrCode::WrongParam;
310
311
0
  Lerc2 lerc2;
312
0
  if (version >= 0 && !lerc2.SetEncoderToOldVersion(version))
313
0
    return ErrCode::WrongParam;
314
315
0
  bool rv = pBitMask ? lerc2.Set(nDim, nCols, nRows, pBitMask->Bits()) : lerc2.Set(nDim, nCols, nRows);
316
0
  if (!rv)
317
0
    return ErrCode::Failed;
318
319
0
  Byte* pByte = pBuffer;
320
321
  // loop over the bands, encode into array of single band Lerc blobs
322
0
  for (int iBand = 0; iBand < nBands; iBand++)
323
0
  {
324
0
    bool encMsk = (iBand == 0);    // store bit mask with first band only
325
0
    const T* arr = pData + nDim * nCols * nRows * iBand;
326
327
0
    ErrCode errCode = CheckForNaN(arr, nDim, nCols, nRows, pBitMask);
328
0
    if (errCode != ErrCode::Ok)
329
0
      return errCode;
330
331
0
    unsigned int nBytes = lerc2.ComputeNumBytesNeededToWrite(arr, maxZErr, encMsk);
332
0
    if (nBytes == 0)
333
0
      return ErrCode::Failed;
334
335
0
    unsigned int nBytesAlloc = nBytes;
336
337
0
    if ((size_t)(pByte - pBuffer) + nBytesAlloc > numBytesBuffer)    // check we have enough space left
338
0
      return ErrCode::BufferTooSmall;
339
340
0
    if (!lerc2.Encode(arr, &pByte))
341
0
      return ErrCode::Failed;
342
0
  }
343
344
0
  numBytesWritten = (unsigned int)(pByte - pBuffer);
345
0
  return ErrCode::Ok;
346
0
}
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<signed char>(signed char const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<unsigned char>(unsigned char const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<short>(short const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<unsigned short>(unsigned short const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<int>(int const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<unsigned int>(unsigned int const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<float>(float const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::EncodeTempl<double>(double const*, int, int, int, int, int, GDAL_LercNS::BitMask const*, double, unsigned char*, unsigned int, unsigned int&)
347
348
// -------------------------------------------------------------------------- ;
349
350
template<class T>
351
ErrCode Lerc::DecodeTempl(T* pData, const Byte* pLercBlob, unsigned int numBytesBlob,
352
  int nDim, int nCols, int nRows, int nBands, BitMask* pBitMask)
353
0
{
354
0
  if (!pData || nDim <= 0 || nCols <= 0 || nRows <= 0 || nBands <= 0 || !pLercBlob || !numBytesBlob)
355
0
    return ErrCode::WrongParam;
356
357
0
  if (pBitMask && (pBitMask->GetHeight() != nRows || pBitMask->GetWidth() != nCols))
358
0
    return ErrCode::WrongParam;
359
360
0
  const Byte* pByte = pLercBlob;
361
#ifdef HAVE_LERC1_DECODE
362
  Byte* pByte1 = const_cast<Byte*>(pLercBlob);
363
#endif
364
0
  Lerc2::HeaderInfo hdInfo;
365
366
0
  if (Lerc2::GetHeaderInfo(pByte, numBytesBlob, hdInfo) && hdInfo.version >= 1)    // is Lerc2
367
0
  {
368
0
    size_t nBytesRemaining = numBytesBlob;
369
0
    Lerc2 lerc2;
370
371
0
    for (int iBand = 0; iBand < nBands; iBand++)
372
0
    {
373
0
      if (((size_t)(pByte - pLercBlob) < numBytesBlob) && Lerc2::GetHeaderInfo(pByte, nBytesRemaining, hdInfo))
374
0
      {
375
0
        if (hdInfo.nDim != nDim || hdInfo.nCols != nCols || hdInfo.nRows != nRows)
376
0
          return ErrCode::Failed;
377
378
0
        if ((pByte - pLercBlob) + (size_t)hdInfo.blobSize > numBytesBlob)
379
0
          return ErrCode::BufferTooSmall;
380
381
0
        T* arr = pData + nDim * nCols * nRows * iBand;
382
383
0
        if (!lerc2.Decode(&pByte, nBytesRemaining, arr, (pBitMask && iBand == 0) ? pBitMask->Bits() : nullptr))
384
0
          return ErrCode::Failed;
385
0
      }
386
0
    }
387
0
  }
388
389
0
  else    // might be old Lerc1
390
0
  {
391
#ifdef HAVE_LERC1_DECODE
392
    unsigned int numBytesHeaderBand0 = CntZImage::computeNumBytesNeededToReadHeader(false);
393
    unsigned int numBytesHeaderBand1 = CntZImage::computeNumBytesNeededToReadHeader(true);
394
    CntZImage zImg;
395
396
    for (int iBand = 0; iBand < nBands; iBand++)
397
    {
398
      unsigned int numBytesHeader = iBand == 0 ? numBytesHeaderBand0 : numBytesHeaderBand1;
399
      if ((size_t)(pByte - pLercBlob) + numBytesHeader > numBytesBlob)
400
        return ErrCode::BufferTooSmall;
401
402
      bool onlyZPart = iBand > 0;
403
      if (!zImg.read(&pByte1, 1e12, false, onlyZPart))
404
        return ErrCode::Failed;
405
406
      if (zImg.getWidth() != nCols || zImg.getHeight() != nRows)
407
        return ErrCode::Failed;
408
409
      T* arr = pData + nCols * nRows * iBand;
410
411
      if (!Convert(zImg, arr, pBitMask))
412
        return ErrCode::Failed;
413
    }
414
#else
415
0
    return ErrCode::Failed;
416
0
#endif
417
0
  }
418
419
0
  return ErrCode::Ok;
420
0
}
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<signed char>(signed char*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<unsigned char>(unsigned char*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<short>(short*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<unsigned short>(unsigned short*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<int>(int*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<unsigned int>(unsigned int*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<float>(float*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::DecodeTempl<double>(double*, unsigned char const*, unsigned int, int, int, int, int, GDAL_LercNS::BitMask*)
421
422
// -------------------------------------------------------------------------- ;
423
// -------------------------------------------------------------------------- ;
424
425
#ifdef HAVE_LERC1_DECODE
426
template<class T>
427
bool Lerc::Convert(const CntZImage& zImg, T* arr, BitMask* pBitMask)
428
{
429
  if (!arr || !zImg.getSize())
430
    return false;
431
432
  const bool fltPnt = (typeid(*arr) == typeid(double)) || (typeid(*arr) == typeid(float));
433
434
  int h = zImg.getHeight();
435
  int w = zImg.getWidth();
436
437
  if (pBitMask && (pBitMask->GetHeight() != h || pBitMask->GetWidth() != w))
438
    return false;
439
440
  if (pBitMask)
441
    pBitMask->SetAllValid();
442
443
  const CntZ* srcPtr = zImg.getData();
444
  T* dstPtr = arr;
445
  int num = w * h;
446
  for (int k = 0; k < num; k++)
447
  {
448
    if (srcPtr->cnt > 0)
449
      *dstPtr = fltPnt ? (T)srcPtr->z : (T)floor(srcPtr->z + 0.5);
450
    else if (pBitMask)
451
      pBitMask->SetInvalid(k);
452
453
    srcPtr++;
454
    dstPtr++;
455
  }
456
457
  return true;
458
}
459
#endif
460
461
// -------------------------------------------------------------------------- ;
462
463
template<class T>
464
ErrCode Lerc::ConvertToDoubleTempl(const T* pDataIn, size_t nDataValues, double* pDataOut)
465
0
{
466
0
  if (!pDataIn || !nDataValues || !pDataOut)
467
0
    return ErrCode::WrongParam;
468
469
0
  for (size_t k = 0; k < nDataValues; k++)
470
0
    pDataOut[k] = pDataIn[k];
471
472
0
  return ErrCode::Ok;
473
0
}
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ConvertToDoubleTempl<signed char>(signed char const*, unsigned long, double*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ConvertToDoubleTempl<unsigned char>(unsigned char const*, unsigned long, double*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ConvertToDoubleTempl<short>(short const*, unsigned long, double*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ConvertToDoubleTempl<unsigned short>(unsigned short const*, unsigned long, double*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ConvertToDoubleTempl<int>(int const*, unsigned long, double*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ConvertToDoubleTempl<unsigned int>(unsigned int const*, unsigned long, double*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::ConvertToDoubleTempl<float>(float const*, unsigned long, double*)
474
475
// -------------------------------------------------------------------------- ;
476
477
template<class T> ErrCode Lerc::CheckForNaN(const T* arr, int nDim, int nCols, int nRows, const BitMask* pBitMask)
478
0
{
479
0
  if (!arr || nDim <= 0 || nCols <= 0 || nRows <= 0)
480
0
    return ErrCode::WrongParam;
481
482
0
#ifdef CHECK_FOR_NAN
483
484
0
  if (typeid(T) == typeid(double) || typeid(T) == typeid(float))
485
0
  {
486
0
    bool foundNaN = false;
487
488
0
    for (int k = 0, i = 0; i < nRows; i++)
489
0
    {
490
0
      const T* rowArr = &(arr[i * nCols * nDim]);
491
492
0
      if (!pBitMask)    // all valid
493
0
      {
494
0
        for (int n = 0, j = 0; j < nCols; j++, n += nDim)
495
0
          for (int m = 0; m < nDim; m++)
496
0
            if (std::isnan((double)rowArr[n + m]))
497
0
              foundNaN = true;
498
0
      }
499
0
      else    // not all valid
500
0
      {
501
0
        for (int n = 0, j = 0; j < nCols; j++, k++, n += nDim)
502
0
          if (pBitMask->IsValid(k))
503
0
          {
504
0
            for (int m = 0; m < nDim; m++)
505
0
              if (std::isnan((double)rowArr[n + m]))
506
0
                foundNaN = true;
507
0
          }
508
0
      }
509
510
0
      if (foundNaN)
511
0
        return ErrCode::NaN;
512
0
    }
513
0
  }
514
515
0
#endif
516
517
0
  return ErrCode::Ok;
518
0
}
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<signed char>(signed char const*, int, int, int, GDAL_LercNS::BitMask const*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<unsigned char>(unsigned char const*, int, int, int, GDAL_LercNS::BitMask const*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<short>(short const*, int, int, int, GDAL_LercNS::BitMask const*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<unsigned short>(unsigned short const*, int, int, int, GDAL_LercNS::BitMask const*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<int>(int const*, int, int, int, GDAL_LercNS::BitMask const*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<unsigned int>(unsigned int const*, int, int, int, GDAL_LercNS::BitMask const*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<float>(float const*, int, int, int, GDAL_LercNS::BitMask const*)
Unexecuted instantiation: GDAL_LercNS::ErrCode GDAL_LercNS::Lerc::CheckForNaN<double>(double const*, int, int, int, GDAL_LercNS::BitMask const*)
519
520
// -------------------------------------------------------------------------- ;
521