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