Coverage Report

Created: 2025-12-31 08:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/mrf/LERCV1/Lerc1Image.h
Line
Count
Source
1
/*
2
Copyright 2015 - 2024 Esri
3
Licensed under the Apache License, Version 2.0 (the "License");
4
you may not use this file except in compliance with the License.
5
You may obtain a copy of the License at
6
http://www.apache.org/licenses/LICENSE-2.0
7
Unless required by applicable law or agreed to in writing, software
8
distributed under the License is distributed on an "AS IS" BASIS,
9
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
See the License for the specific language governing permissions and
11
limitations under the License.
12
A local copy of the license and additional notices are located with the
13
source distribution at:
14
http://github.com/Esri/lerc/
15
Contributors:  Thomas Maurer
16
               Lucian Plesea
17
*/
18
19
#ifndef LERC1IMAGE_H
20
#define LERC1IMAGE_H
21
22
#include <cstring>
23
#include <vector>
24
25
#ifndef NAMESPACE_LERC1_START
26
#define NAMESPACE_LERC1_START                                                  \
27
    namespace Lerc1NS                                                          \
28
    {
29
#define NAMESPACE_LERC1_END }
30
#define USING_NAMESPACE_LERC1 using namespace Lerc1NS;
31
#endif
32
33
NAMESPACE_LERC1_START
34
static_assert(sizeof(float) == 4, "lerc requires float to be exactly 4 bytes");
35
36
typedef unsigned char Byte;
37
38
/** BitMaskV1 - Convenient and fast access to binary mask bits
39
 * includes RLE compression and decompression
40
 *
41
 */
42
43
class BitMaskV1
44
{
45
  public:
46
2.20k
    BitMaskV1() : m_nRows(0), m_nCols(0)
47
2.20k
    {
48
2.20k
    }
49
50
    int size() const
51
603
    {
52
603
        return 1 + (m_nCols * m_nRows - 1) / 8;
53
603
    }
54
55
    void Set(int k, bool v)
56
245M
    {
57
245M
        if (v)
58
0
            SetValid(k);
59
245M
        else
60
245M
            SetInvalid(k);
61
245M
    }
62
63
    Byte IsValid(int k) const
64
33.6M
    {
65
33.6M
        return (bits[k >> 3] & Bit(k)) != 0;
66
33.6M
    }
67
68
    void resize(int nCols, int nRows)
69
428
    {
70
428
        m_nRows = nRows;
71
428
        m_nCols = nCols;
72
428
        bits.resize(size());
73
428
    }
74
75
    // max RLE compressed size is n + 4 + 2 * (n - 1) / 32767
76
    // Returns encoded size
77
    int RLEcompress(Byte *aRLE) const;
78
    // Encoded size, without doing the work
79
    int RLEsize() const;
80
    // Decompress a RLE bitmask, bitmask size should be already set
81
    // Returns false if input seems wrong
82
    bool RLEdecompress(const Byte *src, size_t sz);
83
84
  private:
85
    int m_nRows, m_nCols;
86
    std::vector<Byte> bits;
87
88
    static Byte Bit(int k)
89
279M
    {
90
279M
        return static_cast<Byte>(0x80 >> (k & 7));
91
279M
    }
92
93
    void SetValid(int k)
94
0
    {
95
0
        bits[k >> 3] |= Bit(k);
96
0
    }
97
98
    void SetInvalid(int k)
99
245M
    {
100
245M
        bits[k >> 3] &= ~Bit(k);
101
245M
    }
102
};
103
104
template <typename T> class TImage
105
{
106
  public:
107
2.20k
    TImage() : width_(0), height_(0)
108
2.20k
    {
109
2.20k
    }
110
111
    ~TImage()
112
2.20k
    {
113
2.20k
    }
114
115
    bool setsize(int width, int height)
116
428
    {
117
428
        width_ = width;
118
428
        height_ = height;
119
428
        values.resize(getSize());
120
428
        return true;
121
428
    }
122
123
    int getWidth() const
124
33.6M
    {
125
33.6M
        return width_;
126
33.6M
    }
127
128
    int getHeight() const
129
3.42k
    {
130
3.42k
        return height_;
131
3.42k
    }
132
133
    int getSize() const
134
245M
    {
135
245M
        return width_ * height_;
136
245M
    }
137
138
    const T &operator()(int row, int col) const
139
0
    {
140
0
        return values[row * width_ + col];
141
0
    }
142
143
    T &operator()(int row, int col)
144
1.38M
    {
145
1.38M
        return values[row * width_ + col];
146
1.38M
    }
147
148
    const T *data() const
149
    {
150
        return values.data();
151
    }
152
153
  private:
154
    int width_, height_;
155
    std::vector<T> values;
156
};
157
158
class Lerc1Image final : public TImage<float>
159
{
160
  protected:
161
    struct InfoFromComputeNumBytes
162
    {
163
        double maxZError;
164
        int numTilesVertCnt;
165
        int numTilesHoriCnt;
166
        int numBytesCnt;
167
        float maxCntInImg;
168
        int numTilesVertZ;
169
        int numTilesHoriZ;
170
        int numBytesZ;
171
        float maxZInImg;
172
173
        InfoFromComputeNumBytes()
174
0
        {
175
0
            std::memset(this, 0, sizeof(*this));
176
0
        }
177
    };
178
179
    bool findTiling(double maxZError, int &numTilesVert, int &numTilesHori,
180
                    int &numBytesOpt, float &maxValInImg) const;
181
182
    bool writeTiles(double maxZError, int numTilesVert, int numTilesHori,
183
                    Byte *bArr, int &numBytes, float &maxValInImg) const;
184
185
    bool readTiles(double maxZErrorInFile, int numTilesVert, int numTilesHori,
186
                   float maxValInImg, Byte *bArr, size_t nRemainingBytes);
187
188
    bool computeZStats(int r0, int r1, int c0, int c1, float &zMin, float &zMax,
189
                       int &numValidPixel, int &numFinite) const;
190
191
    // returns true if all floating point values in the region have the same
192
    // binary representation
193
    bool isallsameval(int r0, int r1, int c0, int c1) const;
194
195
    bool writeZTile(Byte **ppByte, int &numBytes, int r0, int r1, int c0,
196
                    int c1, int numValidPixel, float zMin, float zMax,
197
                    double maxZError) const;
198
199
    bool readZTile(Byte **ppByte, size_t &nRemainingBytes, int r0, int r1,
200
                   int c0, int c1, double maxZErrorInFile, float maxZInImg);
201
202
    unsigned int
203
    computeNumBytesNeededToWrite(double maxZError, bool onlyZPart,
204
                                 InfoFromComputeNumBytes *info) const;
205
206
    std::vector<unsigned int> idataVec;  // temporary buffer
207
    BitMaskV1 mask;
208
209
  public:
210
    /// binary file IO with optional compression
211
    /// (maxZError = 0  means no lossy compression for Z; the mask part is
212
    /// compressed lossless or not at all) read succeeds only if maxZError on
213
    /// file <= maxZError requested (!)
214
215
    Lerc1Image()
216
2.20k
    {
217
2.20k
    }
218
219
    ~Lerc1Image()
220
2.20k
    {
221
2.20k
    }
222
223
    static unsigned int computeNumBytesNeededToWriteVoidImage();
224
225
    // Only initialize the size from the header, if LERC1
226
    static bool getwh(const Byte *ppByte, size_t nBytes, int &w, int &h);
227
228
    void resize(int width, int height)
229
428
    {
230
428
        setsize(width, height);
231
428
        mask.resize(getWidth(), getHeight());
232
428
    }
233
234
    bool IsValid(int row, int col) const
235
33.6M
    {
236
33.6M
        return mask.IsValid(row * getWidth() + col) != 0;
237
33.6M
    }
238
239
    void SetMask(int row, int col, bool v)
240
0
    {
241
0
        mask.Set(row * getWidth() + col, v);
242
0
    }
243
244
    // Read and write into a memory buffer
245
    bool write(Byte **ppByte, double maxZError = 0,
246
               bool onlyZPart = false) const;
247
    bool read(Byte **ppByte, size_t &nRemainingBytes, double maxZError,
248
              bool onlyZPart = false);
249
};
250
251
NAMESPACE_LERC1_END
252
#endif