LCOV - code coverage report
Current view: top level - third_party/LercLib - Lerc2.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 202 231 87.4 %
Date: 2024-11-21 22:18:42 Functions: 14 16 87.5 %

          Line data    Source code
       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             :                 Lucian Plesea (provided checksum code)
      23             : */
      24             : 
      25             : #include "Defines.h"
      26             : #include "Lerc2.h"
      27             : 
      28             : USING_NAMESPACE_LERC
      29             : using namespace std;
      30             : 
      31           0 : static void ignore_ret_val(bool) {}
      32             : 
      33             : // -------------------------------------------------------------------------- ;
      34             : 
      35        7323 : Lerc2::Lerc2()
      36             : {
      37        7323 :   Init();
      38        7323 : }
      39             : 
      40             : // -------------------------------------------------------------------------- ;
      41             : 
      42           0 : Lerc2::Lerc2(int nDim, int nCols, int nRows, const Byte* pMaskBits)
      43             : {
      44           0 :   Init();
      45           0 :   ignore_ret_val(Set(nDim, nCols, nRows, pMaskBits));
      46           0 : }
      47             : 
      48             : // -------------------------------------------------------------------------- ;
      49             : 
      50        5180 : bool Lerc2::SetEncoderToOldVersion(int version)
      51             : {
      52        5180 :   if (version < 2 || version > kCurrVersion)
      53           0 :     return false;
      54             : 
      55        5180 :   if (version < 4 && m_headerInfo.nDim > 1)
      56           0 :     return false;
      57             : 
      58        5180 :   m_headerInfo.version = version;
      59             : 
      60        5180 :   return true;
      61             : }
      62             : 
      63             : // -------------------------------------------------------------------------- ;
      64             : 
      65        7323 : void Lerc2::Init()
      66             : {
      67        7323 :   m_microBlockSize    = 8;
      68        7323 :   m_maxValToQuantize  = 0;
      69        7323 :   m_encodeMask        = true;
      70        7323 :   m_writeDataOneSweep = false;
      71        7323 :   m_imageEncodeMode   = IEM_Tiling;
      72             : 
      73        7323 :   m_headerInfo.RawInit();
      74        7323 :   m_headerInfo.version = kCurrVersion;
      75        7323 :   m_headerInfo.microBlockSize = m_microBlockSize;
      76        7323 : }
      77             : 
      78             : // -------------------------------------------------------------------------- ;
      79             : 
      80        5181 : bool Lerc2::Set(int nDim, int nCols, int nRows, const Byte* pMaskBits)
      81             : {
      82        5181 :   if (nDim > 1 && m_headerInfo.version < 4)
      83           0 :     return false;
      84             : 
      85        5181 :   if (!m_bitMask.SetSize(nCols, nRows))
      86           0 :     return false;
      87             : 
      88        5181 :   if (pMaskBits)
      89             :   {
      90          18 :     memcpy(m_bitMask.Bits(), pMaskBits, m_bitMask.Size());
      91          18 :     m_headerInfo.numValidPixel = m_bitMask.CountValidBits();
      92             :   }
      93             :   else
      94             :   {
      95        5163 :     m_headerInfo.numValidPixel = nCols * nRows;
      96        5163 :     m_bitMask.SetAllValid();
      97             :   }
      98             : 
      99        5181 :   m_headerInfo.nDim  = nDim;
     100        5181 :   m_headerInfo.nCols = nCols;
     101        5181 :   m_headerInfo.nRows = nRows;
     102             : 
     103        5181 :   return true;
     104             : }
     105             : 
     106             : // -------------------------------------------------------------------------- ;
     107             : 
     108             : //// if the Lerc2 header should ever shrink in size to less than below, then update it (very unlikely)
     109             : //
     110             : //unsigned int Lerc2::MinNumBytesNeededToReadHeader()
     111             : //{
     112             : //  unsigned int numBytes = (unsigned int)FileKey().length();
     113             : //  numBytes += 7 * sizeof(int);
     114             : //  numBytes += 3 * sizeof(double);
     115             : //  return numBytes;
     116             : //}
     117             : 
     118             : // -------------------------------------------------------------------------- ;
     119             : 
     120        5346 : bool Lerc2::GetHeaderInfo(const Byte* pByte, size_t nBytesRemaining, struct HeaderInfo& hd)
     121             : {
     122        5346 :   if (!pByte || !IsLittleEndianSystem())
     123           0 :     return false;
     124             : 
     125        5346 :   return ReadHeader(&pByte, nBytesRemaining, hd);
     126             : }
     127             : 
     128             : // -------------------------------------------------------------------------- ;
     129             : // -------------------------------------------------------------------------- ;
     130             : 
     131        5181 : unsigned int Lerc2::ComputeNumBytesHeaderToWrite(const struct HeaderInfo& hd)
     132             : {
     133        5181 :   unsigned int numBytes = (unsigned int)FileKey().length();
     134        5181 :   numBytes += 1 * sizeof(int);
     135        5181 :   numBytes += (hd.version >= 3 ? 1 : 0) * sizeof(unsigned int);
     136        5181 :   numBytes += (hd.version >= 4 ? 7 : 6) * sizeof(int);
     137        5181 :   numBytes += 3 * sizeof(double);
     138        5181 :   return numBytes;
     139             : }
     140             : 
     141             : // -------------------------------------------------------------------------- ;
     142             : 
     143        5180 : bool Lerc2::WriteHeader(Byte** ppByte, const struct HeaderInfo& hd)
     144             : {
     145        5180 :   if (!ppByte)
     146           0 :     return false;
     147             : 
     148        5180 :   Byte* ptr = *ppByte;
     149             : 
     150       10360 :   string fileKey = FileKey();
     151        5181 :   size_t len = fileKey.length();
     152        5181 :   memcpy(ptr, fileKey.c_str(), len);
     153        5181 :   ptr += len;
     154             : 
     155        5181 :   memcpy(ptr, &hd.version, sizeof(int));
     156        5181 :   ptr += sizeof(int);
     157             : 
     158        5181 :   if (hd.version >= 3)
     159             :   {
     160         369 :     unsigned int checksum = 0;
     161         369 :     memcpy(ptr, &checksum, sizeof(unsigned int));    // place holder to be filled by the real check sum later
     162         369 :     ptr += sizeof(unsigned int);
     163             :   }
     164             : 
     165       10361 :   vector<int> intVec;
     166        5181 :   intVec.push_back(hd.nRows);
     167        5181 :   intVec.push_back(hd.nCols);
     168             : 
     169        5181 :   if (hd.version >= 4)
     170             :   {
     171         370 :     intVec.push_back(hd.nDim);
     172             :   }
     173             : 
     174        5181 :   intVec.push_back(hd.numValidPixel);
     175        5181 :   intVec.push_back(hd.microBlockSize);
     176        5181 :   intVec.push_back(hd.blobSize);
     177        5181 :   intVec.push_back((int)hd.dt);
     178             : 
     179        5180 :   len = intVec.size() * sizeof(int);
     180        5180 :   memcpy(ptr, &intVec[0], len);
     181        5181 :   ptr += len;
     182             : 
     183        5181 :   vector<double> dblVec;
     184        5180 :   dblVec.push_back(hd.maxZError);
     185        5180 :   dblVec.push_back(hd.zMin);
     186        5181 :   dblVec.push_back(hd.zMax);
     187             : 
     188        5181 :   len = dblVec.size() * sizeof(double);
     189        5181 :   memcpy(ptr, &dblVec[0], len);
     190        5181 :   ptr += len;
     191             : 
     192        5181 :   *ppByte = ptr;
     193        5181 :   return true;
     194             : }
     195             : 
     196             : // -------------------------------------------------------------------------- ;
     197             : 
     198        7488 : bool Lerc2::ReadHeader(const Byte** ppByte, size_t& nBytesRemainingInOut, struct HeaderInfo& hd)
     199             : {
     200        7488 :   if (!ppByte || !*ppByte)
     201           0 :     return false;
     202             : 
     203        7488 :   const Byte* ptr = *ppByte;
     204        7488 :   size_t nBytesRemaining = nBytesRemainingInOut;
     205             : 
     206       14976 :   string fileKey = FileKey();
     207        7488 :   size_t keyLen = fileKey.length();
     208             : 
     209        7488 :   hd.RawInit();
     210             : 
     211        7488 :   if (nBytesRemaining < keyLen || memcmp(ptr, fileKey.c_str(), keyLen))
     212         531 :     return false;
     213             : 
     214        6957 :   ptr += keyLen;
     215        6957 :   nBytesRemaining -= keyLen;
     216             : 
     217        6957 :   if (nBytesRemaining < sizeof(int) || !memcpy(&(hd.version), ptr, sizeof(int)))
     218           0 :     return false;
     219             : 
     220        6957 :   ptr += sizeof(int);
     221        6957 :   nBytesRemaining -= sizeof(int);
     222             : 
     223        6957 :   if (hd.version > kCurrVersion)    // this reader is outdated
     224           0 :     return false;
     225             : 
     226        6957 :   if (hd.version >= 3)
     227             :   {
     228        2123 :     if (nBytesRemaining < sizeof(unsigned int) || !memcpy(&(hd.checksum), ptr, sizeof(unsigned int)))
     229           0 :       return false;
     230             : 
     231        2123 :     ptr += sizeof(unsigned int);
     232        2123 :     nBytesRemaining -= sizeof(unsigned int);
     233             :   }
     234             : 
     235        6957 :   int nInts = (hd.version >= 4) ? 7 : 6;
     236       13914 :   vector<int> intVec(nInts, 0);
     237       13914 :   vector<double> dblVec(3, 0);
     238             : 
     239        6957 :   size_t len = sizeof(int) * intVec.size();
     240             : 
     241        6957 :   if (nBytesRemaining < len || !memcpy(&intVec[0], ptr, len))
     242           0 :     return false;
     243             : 
     244        6957 :   ptr += len;
     245        6957 :   nBytesRemaining -= len;
     246             : 
     247        6957 :   len = sizeof(double) * dblVec.size();
     248             : 
     249        6957 :   if (nBytesRemaining < len || !memcpy(&dblVec[0], ptr, len))
     250           0 :     return false;
     251             : 
     252        6957 :   ptr += len;
     253        6957 :   nBytesRemaining -= len;
     254             : 
     255        6957 :   int i = 0;
     256        6957 :   hd.nRows          = intVec[i++];
     257        6957 :   hd.nCols          = intVec[i++];
     258        6957 :   hd.nDim           = (hd.version >= 4) ? intVec[i++] : 1;
     259        6957 :   hd.numValidPixel  = intVec[i++];
     260        6957 :   hd.microBlockSize = intVec[i++];
     261        6957 :   hd.blobSize       = intVec[i++];
     262        6957 :   const int dt      = intVec[i++];
     263        6957 :   if( dt < DT_Char || dt > DT_Undefined )
     264           0 :     return false;
     265        6957 :   hd.dt             = static_cast<DataType>(dt);
     266             : 
     267        6957 :   hd.maxZError      = dblVec[0];
     268        6957 :   hd.zMin           = dblVec[1];
     269        6957 :   hd.zMax           = dblVec[2];
     270             : 
     271        6957 :   if (hd.nRows <= 0 || hd.nCols <= 0 || hd.nDim <= 0 || hd.numValidPixel < 0 || hd.microBlockSize <= 0 || hd.blobSize <= 0)
     272           0 :     return false;
     273             : 
     274        6957 :   *ppByte = ptr;
     275        6957 :   nBytesRemainingInOut = nBytesRemaining;
     276             : 
     277        6957 :   return true;
     278             : }
     279             : 
     280             : // -------------------------------------------------------------------------- ;
     281             : 
     282        5181 : bool Lerc2::WriteMask(Byte** ppByte) const
     283             : {
     284        5181 :   if (!ppByte)
     285           0 :     return false;
     286             : 
     287        5181 :   int numValid = m_headerInfo.numValidPixel;
     288        5181 :   int numTotal = m_headerInfo.nCols * m_headerInfo.nRows;
     289             : 
     290        5181 :   bool needMask = numValid > 0 && numValid < numTotal;
     291             : 
     292        5181 :   Byte* ptr = *ppByte;
     293             : 
     294        5181 :   if (needMask && m_encodeMask)
     295             :   {
     296             :     Byte* pArrRLE;
     297             :     size_t numBytesRLE;
     298           9 :     RLE rle;
     299           9 :     if (!rle.compress((const Byte*)m_bitMask.Bits(), m_bitMask.Size(), &pArrRLE, numBytesRLE, false))
     300           0 :       return false;
     301             : 
     302           9 :     int numBytesMask = (int)numBytesRLE;
     303           9 :     memcpy(ptr, &numBytesMask, sizeof(int));    // num bytes for compressed mask
     304           9 :     ptr += sizeof(int);
     305           9 :     memcpy(ptr, pArrRLE, numBytesRLE);
     306           9 :     ptr += numBytesRLE;
     307             : 
     308          18 :     delete[] pArrRLE;
     309             :   }
     310             :   else
     311             :   {
     312        5172 :     memset(ptr, 0, sizeof(int));    // indicates no mask stored
     313        5172 :     ptr += sizeof(int);
     314             :   }
     315             : 
     316        5181 :   *ppByte = ptr;
     317        5181 :   return true;
     318             : }
     319             : 
     320             : // -------------------------------------------------------------------------- ;
     321             : 
     322        2142 : bool Lerc2::ReadMask(const Byte** ppByte, size_t& nBytesRemainingInOut)
     323             : {
     324        2142 :   if (!ppByte)
     325           0 :     return false;
     326             : 
     327        2142 :   int numValid = m_headerInfo.numValidPixel;
     328        2142 :   int w = m_headerInfo.nCols;
     329        2142 :   int h = m_headerInfo.nRows;
     330             : 
     331        2142 :   const Byte* ptr = *ppByte;
     332        2142 :   size_t nBytesRemaining = nBytesRemainingInOut;
     333             : 
     334             :   int numBytesMask;
     335        2142 :   if (nBytesRemaining < sizeof(int) || !memcpy(&numBytesMask, ptr, sizeof(int)))
     336           0 :     return false;
     337             : 
     338        2142 :   ptr += sizeof(int);
     339        2142 :   nBytesRemaining -= sizeof(int);
     340             : 
     341        2142 :   if (numValid == 0 || numValid == w * h)
     342             :   {
     343        2133 :     if (numBytesMask != 0)
     344           0 :       return false;
     345             :   }
     346             : 
     347        2142 :   if (!m_bitMask.SetSize(w, h))
     348           0 :     return false;
     349             : 
     350        2142 :   if (numValid == 0)
     351           9 :     m_bitMask.SetAllInvalid();
     352        2133 :   else if (numValid == w * h)
     353        2124 :     m_bitMask.SetAllValid();
     354           9 :   else if (numBytesMask > 0)    // read it in
     355             :   {
     356           9 :     if (nBytesRemaining < static_cast<size_t>(numBytesMask))
     357           0 :       return false;
     358             : 
     359           9 :     RLE rle;
     360           9 :     if (!rle.decompress(ptr, nBytesRemaining, m_bitMask.Bits(), m_bitMask.Size()))
     361           0 :       return false;
     362             : 
     363           9 :     ptr += numBytesMask;
     364           9 :     nBytesRemaining -= numBytesMask;
     365             :   }
     366             :   // else use previous mask
     367             : 
     368        2142 :   *ppByte = ptr;
     369        2142 :   nBytesRemainingInOut = nBytesRemaining;
     370             : 
     371        2142 :   return true;
     372             : }
     373             : 
     374             : // -------------------------------------------------------------------------- ;
     375             : 
     376        5180 : bool Lerc2::DoChecksOnEncode(Byte* pBlobBegin, Byte* pBlobEnd) const
     377             : {
     378        5180 :   if ((size_t)(pBlobEnd - pBlobBegin) != (size_t)m_headerInfo.blobSize)
     379           0 :     return false;
     380             : 
     381        5180 :   if (m_headerInfo.version >= 3)
     382             :   {
     383         370 :     int blobSize = (int)(pBlobEnd - pBlobBegin);
     384         370 :     int nBytes = (int)(FileKey().length() + sizeof(int) + sizeof(unsigned int));    // start right after the checksum entry
     385         369 :     if (blobSize < nBytes)
     386           0 :       return false;
     387         369 :     unsigned int checksum = ComputeChecksumFletcher32(pBlobBegin + nBytes, blobSize - nBytes);
     388             : 
     389         369 :     nBytes -= sizeof(unsigned int);
     390         369 :     memcpy(pBlobBegin + nBytes, &checksum, sizeof(unsigned int));
     391             :   }
     392             : 
     393        5179 :   return true;
     394             : }
     395             : 
     396             : // -------------------------------------------------------------------------- ;
     397             : 
     398             : // from  https://en.wikipedia.org/wiki/Fletcher's_checksum
     399             : // modified from ushorts to bytes (by Lucian Plesea)
     400             : 
     401         901 : unsigned int Lerc2::ComputeChecksumFletcher32(const Byte* pByte, int len)
     402             : {
     403         901 :   unsigned int sum1 = 0xffff, sum2 = 0xffff;
     404         901 :   unsigned int words = len / 2;
     405             : 
     406        7554 :   while (words)
     407             :   {
     408        6653 :     unsigned int tlen = (words >= 359) ? 359 : words;
     409        6653 :     words -= tlen;
     410     2209730 :     do {
     411     2216380 :       sum1 += (*pByte++ << 8);
     412     2216380 :       sum2 += sum1 += *pByte++;
     413     2216380 :     } while (--tlen);
     414             : 
     415        6653 :     sum1 = (sum1 & 0xffff) + (sum1 >> 16);
     416        6653 :     sum2 = (sum2 & 0xffff) + (sum2 >> 16);
     417             :   }
     418             : 
     419             :   // add the straggler byte if it exists
     420         901 :   if (len & 1)
     421         466 :     sum2 += sum1 += (*pByte << 8);
     422             : 
     423             :   // second reduction step to reduce sums to 16 bits
     424         901 :   sum1 = (sum1 & 0xffff) + (sum1 >> 16);
     425         901 :   sum2 = (sum2 & 0xffff) + (sum2 >> 16);
     426             : 
     427         901 :   return sum2 << 16 | sum1;
     428             : }
     429             : 
     430             : // -------------------------------------------------------------------------- ;
     431             : 
     432             : //struct MyLessThanOp
     433             : //{
     434             : //  inline bool operator() (const pair<unsigned int, unsigned int>& p0,
     435             : //                          const pair<unsigned int, unsigned int>& p1)  { return p0.first < p1.first; }
     436             : //};
     437             : 
     438             : // -------------------------------------------------------------------------- ;
     439             : 
     440      709569 : void Lerc2::SortQuantArray(const vector<unsigned int>& quantVec, vector<pair<unsigned int, unsigned int> >& sortedQuantVec)
     441             : {
     442      709569 :   int numElem = (int)quantVec.size();
     443      709569 :   sortedQuantVec.resize(numElem);
     444             : 
     445    71881600 :   for (int i = 0; i < numElem; i++)
     446    71172000 :     sortedQuantVec[i] = pair<unsigned int, unsigned int>(quantVec[i], i);
     447             : 
     448             :   //std::sort(sortedQuantVec.begin(), sortedQuantVec.end(), MyLessThanOp());
     449             : 
     450      709569 :   std::sort(sortedQuantVec.begin(), sortedQuantVec.end(),
     451   371995000 :     [](const pair<unsigned int, unsigned int>& p0,
     452   371995000 :        const pair<unsigned int, unsigned int>& p1) { return p0.first < p1.first; });
     453      709569 : }
     454             : 
     455             : // -------------------------------------------------------------------------- ;
     456             : 

Generated by: LCOV version 1.14