1 /*
2 Copyright 2016 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_c_api.h"
26 #include "Lerc_types.h"
27 #include "Lerc.h"
28 
29 USING_NAMESPACE_LERC
30 
31 // -------------------------------------------------------------------------- ;
32 
33 lerc_status lerc_computeCompressedSize(const void* pData, unsigned int dataType, int nDim, int nCols, int nRows, int nBands,
34   const unsigned char* pValidBytes, double maxZErr, unsigned int* numBytes)
35 {
36   return lerc_computeCompressedSizeForVersion(pData, -1, dataType, nDim, nCols, nRows, nBands, pValidBytes, maxZErr, numBytes);
37 }
38 
39 // -------------------------------------------------------------------------- ;
40 
41 lerc_status lerc_computeCompressedSizeForVersion(const void* pData, int version, unsigned int dataType, int nDim, int nCols, int nRows, int nBands,
42   const unsigned char* pValidBytes, double maxZErr, unsigned int* numBytes)
43 {
44   if (!pData || dataType >= Lerc::DT_Undefined || nDim <= 0 || nCols <= 0 || nRows <= 0 || nBands <= 0 || maxZErr < 0 || !numBytes)
45     return (lerc_status)ErrCode::WrongParam;
46 
47   BitMask bitMask;
48   if (pValidBytes)
49   {
50     bitMask.SetSize(nCols, nRows);
51     bitMask.SetAllValid();
52 
53     for (int k = 0, i = 0; i < nRows; i++)
54       for (int j = 0; j < nCols; j++, k++)
55         if (!pValidBytes[k])
56           bitMask.SetInvalid(k);
57   }
58   const BitMask* pBitMask = pValidBytes ? &bitMask : nullptr;
59 
60   Lerc::DataType dt = (Lerc::DataType)dataType;
61   return (lerc_status)Lerc::ComputeCompressedSize(pData, version, dt, nDim, nCols, nRows, nBands, pBitMask, maxZErr, *numBytes);
62 }
63 
64 // -------------------------------------------------------------------------- ;
65 
66 lerc_status lerc_encode(const void* pData, unsigned int dataType, int nDim, int nCols, int nRows, int nBands,
67   const unsigned char* pValidBytes, double maxZErr, unsigned char* pOutBuffer, unsigned int outBufferSize,
68   unsigned int* nBytesWritten)
69 {
70   return lerc_encodeForVersion(pData, -1, dataType, nDim, nCols, nRows, nBands, pValidBytes, maxZErr, pOutBuffer, outBufferSize, nBytesWritten);
71 }
72 
73 // -------------------------------------------------------------------------- ;
74 
75 lerc_status lerc_encodeForVersion(const void* pData, int version, unsigned int dataType, int nDim, int nCols, int nRows, int nBands,
76   const unsigned char* pValidBytes, double maxZErr, unsigned char* pOutBuffer, unsigned int outBufferSize,
77   unsigned int* nBytesWritten)
78 {
79   if (!pData || dataType >= Lerc::DT_Undefined || nDim <= 0 || nCols <= 0 || nRows <= 0 || nBands <= 0 || maxZErr < 0 || !pOutBuffer || !outBufferSize || !nBytesWritten)
80     return (lerc_status)ErrCode::WrongParam;
81 
82   BitMask bitMask;
83   if (pValidBytes)
84   {
85     bitMask.SetSize(nCols, nRows);
86     bitMask.SetAllValid();
87 
88     for (int k = 0, i = 0; i < nRows; i++)
89       for (int j = 0; j < nCols; j++, k++)
90         if (!pValidBytes[k])
91           bitMask.SetInvalid(k);
92   }
93   const BitMask* pBitMask = pValidBytes ? &bitMask : nullptr;
94 
95   Lerc::DataType dt = (Lerc::DataType)dataType;
96   return (lerc_status)Lerc::Encode(pData, version, dt, nDim, nCols, nRows, nBands, pBitMask, maxZErr, pOutBuffer, outBufferSize, *nBytesWritten);
97 }
98 
99 // -------------------------------------------------------------------------- ;
100 
101 lerc_status lerc_getBlobInfo(const unsigned char* pLercBlob, unsigned int blobSize,
102   unsigned int* infoArray, double* dataRangeArray, int infoArraySize, int dataRangeArraySize)
103 {
104   if (!pLercBlob || !blobSize || (!infoArray && !dataRangeArray) || ((infoArraySize <= 0) && (dataRangeArraySize <= 0)))
105     return (lerc_status)ErrCode::WrongParam;
106 
107   Lerc::LercInfo lercInfo;
108   ErrCode errCode = Lerc::GetLercInfo(pLercBlob, blobSize, lercInfo);
109   if (errCode != ErrCode::Ok)
110     return (lerc_status)errCode;
111 
112   if (infoArray)
113   {
114     int i = 0, ias = infoArraySize;
115 
116     if (ias > 0)
117       memset(infoArray, 0, ias * sizeof(infoArray[0]));
118 
119     if (i < ias)
120       infoArray[i++] = (unsigned int)lercInfo.version;
121     if (i < ias)
122       infoArray[i++] = (unsigned int)lercInfo.dt;
123     if (i < ias)
124       infoArray[i++] = (unsigned int)lercInfo.nDim;
125     if (i < ias)
126       infoArray[i++] = (unsigned int)lercInfo.nCols;
127     if (i < ias)
128       infoArray[i++] = (unsigned int)lercInfo.nRows;
129     if (i < ias)
130       infoArray[i++] = (unsigned int)lercInfo.nBands;
131     if (i < ias)
132       infoArray[i++] = (unsigned int)lercInfo.numValidPixel;
133     if (i < ias)
134       infoArray[i++] = (unsigned int)lercInfo.blobSize;
135   }
136 
137   if (dataRangeArray)
138   {
139     int i = 0, dras = dataRangeArraySize;
140 
141     if (dras > 0)
142       memset(dataRangeArray, 0, dras * sizeof(dataRangeArray[0]));
143 
144     if (i < dras)
145       dataRangeArray[i++] = lercInfo.zMin;
146     if (i < dras)
147       dataRangeArray[i++] = lercInfo.zMax;
148     if (i < dras)
149       dataRangeArray[i++] = lercInfo.maxZError;
150   }
151 
152   return (lerc_status)ErrCode::Ok;
153 }
154 
155 // -------------------------------------------------------------------------- ;
156 
157 lerc_status lerc_decode(const unsigned char* pLercBlob, unsigned int blobSize,
158   unsigned char* pValidBytes, int nDim, int nCols, int nRows, int nBands, unsigned int dataType, void* pData)
159 {
160   if (!pLercBlob || !blobSize || !pData || dataType >= Lerc::DT_Undefined || nDim <= 0 || nCols <= 0 || nRows <= 0 || nBands <= 0)
161     return (lerc_status)ErrCode::WrongParam;
162 
163   BitMask bitMask;
164   if (pValidBytes)
165   {
166     bitMask.SetSize(nCols, nRows);
167     bitMask.SetAllInvalid();
168   }
169   BitMask* pBitMask = pValidBytes ? &bitMask : nullptr;
170 
171   Lerc::DataType dt = (Lerc::DataType)dataType;
172 
173   ErrCode errCode = Lerc::Decode(pLercBlob, blobSize, pBitMask, nDim, nCols, nRows, nBands, dt, pData);
174   if (errCode != ErrCode::Ok)
175     return (lerc_status)errCode;
176 
177   if (pValidBytes)
178   {
179     for (int k = 0, i = 0; i < nRows; i++)
180       for (int j = 0; j < nCols; j++, k++)
181         pValidBytes[k] = bitMask.IsValid(k);
182   }
183 
184   return (lerc_status)ErrCode::Ok;
185 }
186 
187 // -------------------------------------------------------------------------- ;
188 
189 lerc_status lerc_decodeToDouble(const unsigned char* pLercBlob, unsigned int blobSize,
190   unsigned char* pValidBytes, int nDim, int nCols, int nRows, int nBands, double* pData)
191 {
192   if (!pLercBlob || !blobSize || !pData || nDim <= 0 || nCols <= 0 || nRows <= 0 || nBands <= 0)
193     return (lerc_status)ErrCode::WrongParam;
194 
195   Lerc::LercInfo lercInfo;
196   ErrCode errCode;
197   if ((errCode = Lerc::GetLercInfo(pLercBlob, blobSize, lercInfo)) != ErrCode::Ok)
198     return (lerc_status)errCode;
199 
200   Lerc::DataType dt = lercInfo.dt;
201   if (dt > Lerc::DT_Double)
202     return (lerc_status)ErrCode::Failed;
203 
204   BitMask bitMask;
205   if (pValidBytes)
206   {
207     bitMask.SetSize(nCols, nRows);
208     bitMask.SetAllInvalid();
209   }
210   BitMask* pBitMask = pValidBytes ? &bitMask : nullptr;
211 
212   if (dt == Lerc::DT_Double)
213   {
214     if ((errCode = Lerc::Decode(pLercBlob, blobSize, pBitMask, nDim, nCols, nRows, nBands, dt, pData)) != ErrCode::Ok)
215       return (lerc_status)errCode;
216   }
217   else
218   {
219     // use the buffer passed for in place decode and convert
220     int sizeofDt[] = { 1, 1, 2, 2, 4, 4, 4, 8 };
221     size_t nDataValues = nDim * nCols * nRows * nBands;
222     void* ptrDec = (Byte*)pData + nDataValues * (sizeof(double) - sizeofDt[dt]);
223 
224     if ((errCode = Lerc::Decode(pLercBlob, blobSize, pBitMask, nDim, nCols, nRows, nBands, dt, ptrDec)) != ErrCode::Ok)
225       return (lerc_status)errCode;
226 
227     if ((errCode = Lerc::ConvertToDouble(ptrDec, dt, nDataValues, pData)) != ErrCode::Ok)
228       return (lerc_status)errCode;
229   }
230 
231   if (pValidBytes)
232   {
233     for (int k = 0, i = 0; i < nRows; i++)
234       for (int j = 0; j < nCols; j++, k++)
235         pValidBytes[k] = bitMask.IsValid(k);
236   }
237 
238   return (lerc_status)ErrCode::Ok;
239 }
240 
241 // -------------------------------------------------------------------------- ;
242 
243