Line data Source code
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 24 : BitMaskV1() : m_nRows(0), m_nCols(0)
47 : {
48 24 : }
49 :
50 68 : int size() const
51 : {
52 68 : return 1 + (m_nCols * m_nRows - 1) / 8;
53 : }
54 :
55 3145730 : void Set(int k, bool v)
56 : {
57 3145730 : if (v)
58 259297 : SetValid(k);
59 : else
60 2886430 : SetInvalid(k);
61 3145730 : }
62 :
63 20517500 : Byte IsValid(int k) const
64 : {
65 20517500 : return (bits[k >> 3] & Bit(k)) != 0;
66 : }
67 :
68 28 : void resize(int nCols, int nRows)
69 : {
70 28 : m_nRows = nRows;
71 28 : m_nCols = nCols;
72 28 : bits.resize(size());
73 28 : }
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 23663200 : static Byte Bit(int k)
89 : {
90 23663200 : return static_cast<Byte>(0x80 >> (k & 7));
91 : }
92 :
93 259297 : void SetValid(int k)
94 : {
95 259297 : bits[k >> 3] |= Bit(k);
96 259297 : }
97 :
98 2886430 : void SetInvalid(int k)
99 : {
100 2886430 : bits[k >> 3] &= ~Bit(k);
101 2886430 : }
102 : };
103 :
104 : template <typename T> class TImage
105 : {
106 : public:
107 24 : TImage() : width_(0), height_(0)
108 : {
109 24 : }
110 :
111 24 : ~TImage()
112 : {
113 24 : }
114 :
115 28 : bool setsize(int width, int height)
116 : {
117 28 : width_ = width;
118 28 : height_ = height;
119 28 : values.resize(getSize());
120 28 : return true;
121 : }
122 :
123 23913600 : int getWidth() const
124 : {
125 23913600 : return width_;
126 : }
127 :
128 76919 : int getHeight() const
129 : {
130 76919 : return height_;
131 : }
132 :
133 1540 : int getSize() const
134 : {
135 1540 : return width_ * height_;
136 : }
137 :
138 1253600 : const T &operator()(int row, int col) const
139 : {
140 1253600 : return values[row * width_ + col];
141 : }
142 :
143 4471660 : T &operator()(int row, int col)
144 : {
145 4471660 : return values[row * width_ + col];
146 : }
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 : 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 12 : InfoFromComputeNumBytes()
174 12 : {
175 12 : std::memset(this, 0, sizeof(*this));
176 12 : }
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 24 : Lerc1Image()
216 24 : {
217 24 : }
218 :
219 24 : ~Lerc1Image()
220 24 : {
221 24 : }
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 28 : void resize(int width, int height)
229 : {
230 28 : setsize(width, height);
231 28 : mask.resize(getWidth(), getHeight());
232 28 : }
233 :
234 20516000 : bool IsValid(int row, int col) const
235 : {
236 20516000 : return mask.IsValid(row * getWidth() + col) != 0;
237 : }
238 :
239 3145730 : void SetMask(int row, int col, bool v)
240 : {
241 3145730 : mask.Set(row * getWidth() + col, v);
242 3145730 : }
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
|