/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 | | |