Line data Source code
1 : /*
2 : Copyright 2015 - 2021 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 1552 : int getSize() const
134 : {
135 1552 : 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 : void computeCntStats(float &cntMin, float &cntMax)
189 : const; // Across the whole image, always works
190 : bool computeZStats(int r0, int r1, int c0, int c1, float &zMin, float &zMax,
191 : int &numValidPixel, int &numFinite) const;
192 :
193 : // returns true if all floating point values in the region have the same
194 : // binary representation
195 : bool isallsameval(int r0, int r1, int c0, int c1) const;
196 :
197 : bool writeZTile(Byte **ppByte, int &numBytes, int r0, int r1, int c0,
198 : int c1, int numValidPixel, float zMin, float zMax,
199 : double maxZError) const;
200 :
201 : bool readZTile(Byte **ppByte, size_t &nRemainingBytes, int r0, int r1,
202 : int c0, int c1, double maxZErrorInFile, float maxZInImg);
203 :
204 : unsigned int
205 : computeNumBytesNeededToWrite(double maxZError, bool onlyZPart,
206 : InfoFromComputeNumBytes *info) const;
207 :
208 : std::vector<unsigned int>
209 : idataVec; // temporary buffer, reused in readZTile
210 : BitMaskV1 mask;
211 :
212 : public:
213 : /// binary file IO with optional compression
214 : /// (maxZError = 0 means no lossy compression for Z; the mask part is
215 : /// compressed lossless or not at all) read succeeds only if maxZError on
216 : /// file <= maxZError requested (!)
217 :
218 24 : Lerc1Image()
219 24 : {
220 24 : }
221 :
222 24 : ~Lerc1Image()
223 24 : {
224 24 : }
225 :
226 : static unsigned int computeNumBytesNeededToWriteVoidImage();
227 :
228 : // Only initialize the size from the header, if LERC1
229 : static bool getwh(const Byte *ppByte, size_t nBytes, int &w, int &h);
230 :
231 28 : void resize(int width, int height)
232 : {
233 28 : setsize(width, height);
234 28 : mask.resize(getWidth(), getHeight());
235 28 : }
236 :
237 20516000 : bool IsValid(int row, int col) const
238 : {
239 20516000 : return mask.IsValid(row * getWidth() + col) != 0;
240 : }
241 :
242 3145730 : void SetMask(int row, int col, bool v)
243 : {
244 3145730 : mask.Set(row * getWidth() + col, v);
245 3145730 : }
246 :
247 : // Read and write into a memory buffer
248 : bool write(Byte **ppByte, double maxZError = 0,
249 : bool onlyZPart = false) const;
250 : bool read(Byte **ppByte, size_t &nRemainingBytes, double maxZError,
251 : bool onlyZPart = false);
252 : };
253 :
254 : NAMESPACE_LERC1_END
255 : #endif
|