Coverage Report

Created: 2026-06-16 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lerc/src/LercLib/Lerc.h
Line
Count
Source
1
/*
2
Copyright 2015 - 2026 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
#pragma once
25
26
#include <cstring>
27
#include <vector>
28
#include "include/Lerc_types.h"
29
#include "BitMask.h"
30
#include "Lerc2.h"
31
32
NAMESPACE_LERC_START
33
34
#ifdef HAVE_LERC1_DECODE
35
  class CntZImage;
36
#endif
37
38
  class Lerc
39
  {
40
  public:
41
0
    Lerc() {}
42
0
    ~Lerc() {}
43
44
    // data types supported by Lerc
45
    enum DataType { DT_Char, DT_Byte, DT_Short, DT_UShort, DT_Int, DT_UInt, DT_Float, DT_Double, DT_Undefined };
46
47
    // all functions are provided in 2 flavors
48
    // - using void pointers to the image data, can be called on a Lerc lib or dll
49
    // - data templated, can be called if compiled together
50
51
52
    // Encode
53
54
    // if more than 1 band, the outgoing Lerc blob has the single band Lerc blobs concatenated; 
55
    // or, if you have multiple values per pixel and stored as [RGB, RGB, ... ], then set nDepth accordingly (e.g., 3)
56
57
    // computes the number of bytes needed to allocate the buffer, accurate to the byte;
58
    // does not encode the image data, but uses statistics and formulas to compute the buffer size needed;
59
    // this function is optional, you can also use a buffer large enough to call Encode() directly, 
60
    // or, if encoding a batch of same width / height tiles, call this function once, double the buffer size, and
61
    // then just call Encode() on all tiles;
62
63
    static ErrCode ComputeCompressedSize(
64
      const void* pData,               // raw image data, row by row, band by band
65
      int version,                     // 2 = v2.2, 3 = v2.3, 4 = v2.4, 5 = v2.5
66
      DataType dt,                     // data type, char to double
67
      int nDepth,                      // number of values per pixel
68
      int nCols,                       // number of cols
69
      int nRows,                       // number of rows
70
      int nBands,                      // number of bands
71
      int nMasks,                      // number of masks (0, 1, or nBands)
72
      const Byte* pValidBytes,         // masks (size = nMasks * nRows * nCols)
73
      double maxZErr,                  // max coding error per pixel, defines the precision
74
      unsigned int& numBytesNeeded,    // size of outgoing Lerc blob
75
      const unsigned char* pUsesNoData,// if there are invalid values not marked by the mask, pass an array of size nBands, 1 - uses noData, 0 - not
76
      const double* noDataValues);     // same, pass an array of size nBands with noData value per band, or pass nullptr
77
78
    // encodes or compresses the image data into the buffer
79
80
    static ErrCode Encode(
81
      const void* pData,               // raw image data, row by row, band by band
82
      int version,                     // 2 = v2.2, 3 = v2.3, 4 = v2.4, 5 = v2.5
83
      DataType dt,                     // data type, char to double
84
      int nDepth,                      // number of values per pixel
85
      int nCols,                       // number of cols
86
      int nRows,                       // number of rows
87
      int nBands,                      // number of bands
88
      int nMasks,                      // number of masks (0, 1, or nBands)
89
      const Byte* pValidBytes,         // masks (size = nMasks * nRows * nCols)
90
      double maxZErr,                  // max coding error per pixel, defines the precision
91
      Byte* pBuffer,                   // buffer to write to, function fails if buffer too small
92
      unsigned int numBytesBuffer,     // buffer size
93
      unsigned int& numBytesWritten,   // num bytes written to buffer
94
      const unsigned char* pUsesNoData,// if there are invalid values not marked by the mask, pass an array of size nBands, 1 - uses noData, 0 - not
95
      const double* noDataValues);     // same, pass an array of size nBands with noData value per band, or pass nullptr
96
97
    // Decode
98
99
    struct LercInfo
100
    {
101
      int version,        // Lerc version number (0 for old Lerc1, 1 to 5 for Lerc 2.1 to 2.5)
102
        nDepth,           // number of values per pixel
103
        nCols,            // number of columns
104
        nRows,            // number of rows
105
        numValidPixel,    // number of valid pixels
106
        nBands,           // number of bands
107
        blobSize,         // total blob size in bytes
108
        nMasks,           // number of masks (0, 1, or nBands)
109
        nUsesNoDataValue; // 0 - no noData value used, nBands - noData value used in 1 or more bands (only possible for nDepth > 1)
110
      DataType dt;        // data type (float only for old Lerc1)
111
      double zMin,        // min pixel value, over all data values
112
        zMax,             // max pixel value, over all data values
113
        maxZError;        // maxZError used for encoding
114
115
0
      void RawInit()  { memset(this, 0, sizeof(struct LercInfo)); }
116
    };
117
118
    // again, this function is optional;
119
    // call it on a Lerc blob to get the above struct returned, from this the data arrays
120
    // can be constructed before calling Decode();
121
    // same as above, for a batch of Lerc blobs of the same kind, you can call this function on 
122
    // the first blob, get the info, and on the other Lerc blobs just call Decode();
123
    // this function is very fast on (newer) Lerc2 blobs as it only reads the blob headers;
124
125
    // Remark on param numBytesBlob. Usually it is known, either the file size of the blob written to disk, 
126
    // or the size of the blob transmitted. It should be accurate for 2 reasons:
127
    // _ function finds out how many single band Lerc blobs are concatenated
128
    // _ function checks for truncated file or blob
129
    // It is OK to pass numBytesBlob too large as long as there is no other (valid) Lerc blob following next.
130
    // If in doubt, check the code in Lerc::GetLercInfo(...) for the exact logic. 
131
132
    static ErrCode GetLercInfo(const Byte* pLercBlob,       // Lerc blob to decode
133
      unsigned int numBytesBlob,   // size of Lerc blob in bytes
134
      struct LercInfo& lercInfo,
135
      double* pMins = nullptr,     // pass array of size (nDepth * nBands) to get the min values per dimension and band
136
      double* pMaxs = nullptr,     // same as pMins, to get the max values
137
      size_t nElem = 0);           // (nDepth * nBands), if passed
138
139
    // setup outgoing arrays accordingly, then call Decode()
140
141
    static ErrCode Decode(
142
      const Byte* pLercBlob,           // Lerc blob to decode
143
      unsigned int numBytesBlob,       // size of Lerc blob in bytes
144
      int nMasks,                      // number of masks (0, 1, or nBands)
145
      Byte* pValidBytes,               // masks (fails if not big enough to take the masks decoded, fills with 1 if all valid)
146
      int nDepth,                      // number of values per pixel
147
      int nCols,                       // number of cols
148
      int nRows,                       // number of rows
149
      int nBands,                      // number of bands
150
      DataType dt,                     // data type of outgoing array
151
      void* pData,                     // outgoing data bands
152
      unsigned char* pUsesNoData,      // pass an array of size nBands, 1 - band uses noData, 0 - not
153
      double* noDataValues);           // same, pass an array of size nBands to get the noData value per band, if any
154
155
    static ErrCode ConvertToDouble(
156
      const void* pDataIn,             // pixel data of image tile of data type dt (< double)
157
      DataType dt,                     // data type of input data
158
      size_t nDataValues,              // total number of data values (nDepth * nCols * nRows * nBands)
159
      double* pDataOut);               // pixel data converted to double
160
161
162
    // same as functions above, but data templated instead of using void pointers
163
164
    template<class T> static ErrCode ComputeCompressedSizeTempl(
165
      const T* pData,                  // raw image data, row by row, band by 
166
      int version,                     // 2 = v2.2, 3 = v2.3, 4 = v2.4, 5 = v2.5
167
      int nDepth,                      // number of values per pixel
168
      int nCols,                       // number of cols
169
      int nRows,                       // number of rows
170
      int nBands,                      // number of bands
171
      int nMasks,                      // number of masks (0, 1, or nBands)
172
      const Byte* pValidBytes,         // masks (size = nMasks * nRows * nCols)
173
      double maxZErr,                  // max coding error per pixel, defines the precision
174
      unsigned int& numBytes,          // size of outgoing Lerc blob
175
      const unsigned char* pUsesNoData,// if there are invalid values not marked by the mask, pass an array of size nBands, 1 - uses noData, 0 - not
176
      const double* noDataValues);     // same, pass an array of size nBands with noData value per band, or pass nullptr
177
178
    template<class T> static ErrCode EncodeTempl(
179
      const T* pData,                  // raw image data, row by row, band by band
180
      int version,                     // 2 = v2.2, 3 = v2.3, 4 = v2.4 5 = v2.5
181
      int nDepth,                      // number of values per pixel
182
      int nCols,                       // number of cols
183
      int nRows,                       // number of rows
184
      int nBands,                      // number of bands
185
      int nMasks,                      // number of masks (0, 1, or nBands)
186
      const Byte* pValidBytes,         // masks (size = nMasks * nRows * nCols)
187
      double maxZErr,                  // max coding error per pixel, defines the precision
188
      Byte* pBuffer,                   // buffer to write to, function will fail if buffer too small
189
      unsigned int numBytesBuffer,     // buffer size
190
      unsigned int& numBytesWritten,   // num bytes written to buffer
191
      const unsigned char* pUsesNoData,// if there are invalid values not marked by the mask, pass an array of size nBands, 1 - uses noData, 0 - not
192
      const double* noDataValues);     // same, pass an array of size nBands with noData value per band, or pass nullptr
193
194
    template<class T> static ErrCode DecodeTempl(
195
      T* pData,                        // outgoing data bands
196
      const Byte* pLercBlob,           // Lerc blob to decode
197
      unsigned int numBytesBlob,       // size of Lerc blob in bytes
198
      int nDepth,                      // number of values per pixel
199
      int nCols,                       // number of cols
200
      int nRows,                       // number of rows
201
      int nBands,                      // number of bands
202
      int nMasks,                      // number of masks (0, 1, or nBands)
203
      Byte* pValidBytes,               // masks (fails if not big enough to take the masks decoded, fills with 1 if all valid)
204
      unsigned char* pUsesNoData,      // pass an array of size nBands, 1 - band uses noData, 0 - not
205
      double* noDataValues);           // same, pass an array of size nBands to get the noData value per band, if any
206
207
  private:
208
209
    template<class T> static ErrCode EncodeInternal_v5(
210
      const T* pData,                  // raw image data, row by row, band by band
211
      int version,                     // 2 = v2.2, 3 = v2.3, 4 = v2.4, 5 = v2.5
212
      int nDepth,                      // number of values per pixel
213
      int nCols,                       // number of cols
214
      int nRows,                       // number of rows
215
      int nBands,                      // number of bands
216
      int nMasks,                      // number of masks (0, 1, or nBands)
217
      const Byte* pValidBytes,         // masks (size = nMasks * nRows * nCols)
218
      double maxZErr,                  // max coding error per pixel, defines the precision
219
      unsigned int& numBytes,          // size of outgoing Lerc blob
220
      Byte* pBuffer,                   // buffer to write to, function will fail if buffer too small
221
      unsigned int numBytesBuffer,     // buffer size
222
      unsigned int& numBytesWritten);  // num bytes written to buffer
223
224
    template<class T> static ErrCode EncodeInternal(
225
      const T* pData,                  // raw image data, row by row, band by band
226
      int version,                     // 6 = v2.6 (or -1 for current)
227
      int nDepth,                      // number of values per pixel
228
      int nCols,                       // number of cols
229
      int nRows,                       // number of rows
230
      int nBands,                      // number of bands
231
      int nMasks,                      // number of masks (0, 1, or nBands)
232
      const Byte* pValidBytes,         // masks (size = nMasks * nRows * nCols)
233
      double maxZErr,                  // max coding error per pixel, defines the precision
234
      unsigned int& numBytes,          // size of outgoing Lerc blob
235
      Byte* pBuffer,                   // buffer to write to, function will fail if buffer too small
236
      unsigned int numBytesBuffer,     // buffer size
237
      unsigned int& numBytesWritten,   // num bytes written to buffer
238
      const unsigned char* pUsesNoData,// if there are invalid values not marked by the mask, pass an array of size nBands, 1 - uses noData, 0 - not
239
      const double* noDataValues);     // same, pass an array of size nBands with noData value per band, or pass nullptr
240
241
#ifdef HAVE_LERC1_DECODE
242
    template<class T> static bool Convert(const CntZImage& zImg, T* arr, Byte* pByteMask, bool bMustFillMask);
243
#endif
244
    template<class T> static ErrCode ConvertToDoubleTempl(const T* pDataIn, size_t nDataValues, double* pDataOut);
245
246
    template<class T> static ErrCode CheckForNaN(const T* arr, int nDepth, int nCols, int nRows, const Byte* pByteMask);
247
248
    template<class T> static bool ReplaceNaNValues(std::vector<T>& dataBuffer, std::vector<Byte>& maskBuffer, int nDepth, int nCols, int nRows);
249
250
    template<class T> static bool Resize(std::vector<T>& buffer, size_t nElem);
251
252
    static bool Convert(const Byte* pByteMask, int nCols, int nRows, BitMask& bitMask);
253
    static bool Convert(const BitMask& bitMask, Byte* pByteMask);
254
    static bool MasksDiffer(const Byte* p0, const Byte* p1, size_t n);
255
256
    static ErrCode GetRanges(const Byte* pLercBlob, unsigned int numBytesBlob, int iBand,
257
      const struct Lerc2::HeaderInfo& lerc2Info, double* pMins, double* pMaxs, size_t nElem);
258
259
    template<class T>
260
    static bool RemapNoData(T* data, const BitMask& bitMask, const struct Lerc2::HeaderInfo& lerc2Info);
261
262
    template<class T>
263
    static bool DecodeAndCompareToInput(const Byte* pLercBlob, size_t blobSize, double maxZErr, Lerc2& lerc2Verify,
264
      const T* pData, const Byte* pByteMask, const T* pDataOrig, const Byte* pByteMaskOrig,
265
      bool bInputHasNoData, double origNoDataA, bool bModifiedMask);
266
267
    template<class T>
268
    static bool GetTypeRange(const T, std::pair<double, double>& range);
269
270
    template<class T>
271
0
    inline static bool IsInt(T z) { return(z == (T)floor((double)z + 0.5)); };
Unexecuted instantiation: bool LercNS::Lerc::IsInt<signed char>(signed char)
Unexecuted instantiation: bool LercNS::Lerc::IsInt<unsigned char>(unsigned char)
Unexecuted instantiation: bool LercNS::Lerc::IsInt<short>(short)
Unexecuted instantiation: bool LercNS::Lerc::IsInt<unsigned short>(unsigned short)
Unexecuted instantiation: bool LercNS::Lerc::IsInt<int>(int)
Unexecuted instantiation: bool LercNS::Lerc::IsInt<unsigned int>(unsigned int)
Unexecuted instantiation: bool LercNS::Lerc::IsInt<float>(float)
Unexecuted instantiation: bool LercNS::Lerc::IsInt<double>(double)
272
273
    template<class T>
274
    static ErrCode FilterNoData(std::vector<T>& dataBuffer, std::vector<Byte>& maskBuffer, int nDepth, int nCols, int nRows,
275
      double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData,
276
      double& minVal, double& maxVal);
277
278
    template<class T>
279
    static ErrCode FilterNoDataAndNaN(std::vector<T>& dataBuffer, std::vector<Byte>& maskBuffer, int nDepth, int nCols, int nRows,
280
      double& maxZError, bool bPassNoDataValue, double& noDataValue, bool& bModifiedMask, bool& bNeedNoData, bool& bIsFltDblAllInt,
281
      double& minVal, double& maxVal);
282
283
    template<class T>
284
    static bool FindNewNoDataBelowValidMin(double minVal, double maxZErr, bool bAllInt, double lowIntLimit, T& newNoDataVal);
285
  };
286
NAMESPACE_LERC_END