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