LCOV - code coverage report
Current view: top level - frmts/rmf - rmfdem.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 305 345 88.4 %
Date: 2024-05-18 15:15:27 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Raster Matrix Format
       4             :  * Purpose:  Implementation of the ad-hoc compression algorithm used in
       5             :  *           GIS "Panorama"/"Integratsia".
       6             :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2009, Andrey Kiselev <dron@ak4719.spb.edu>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_conv.h"
      31             : 
      32             : #include "rmfdataset.h"
      33             : 
      34             : #include <limits>
      35             : 
      36             : /*
      37             :  * The encoded data stream is a series of records.
      38             :  *
      39             :  * Encoded record consist from the 1-byte record header followed by the
      40             :  * encoded data block. Header specifies the number of elements in the data
      41             :  * block and encoding type. Header format
      42             :  *
      43             :  * +---+---+---+---+---+---+---+---+
      44             :  * |   type    |       count       |
      45             :  * +---+---+---+---+---+---+---+---+
      46             :  *   7   6   5   4   3   2   1   0
      47             :  *
      48             :  * If count is zero then it means that there are more than 31 elements in this
      49             :  * record. Read the next byte in the stream and increase its value with 32 to
      50             :  * get the count. In this case maximum number of elements is 287.
      51             :  *
      52             :  * The "type" field specifies encoding type. It can be either difference
      53             :  * between the previous and the next data value (for the first element the
      54             :  * previous value is zero) or out-of-range codes.
      55             :  *
      56             :  * In case of "out of range" or "zero difference" values there are no more
      57             :  * elements in record after the header. Otherwise read as much encoded
      58             :  * elements as count specifies.
      59             :  */
      60             : 
      61             : typedef GInt32 DEMWorkT;
      62             : typedef GInt64 DEMDiffT;
      63             : 
      64             : // Encoding types
      65             : enum RmfTypes
      66             : {
      67             :     TYPE_OUT = 0x00,    // Value is out of range
      68             :     TYPE_ZERO = 0x20,   // Zero difference
      69             :     TYPE_INT4 = 0x40,   // Difference is 4-bit wide
      70             :     TYPE_INT8 = 0x60,   // Difference is 8-bit wide
      71             :     TYPE_INT12 = 0x80,  // Difference is 12-bit wide
      72             :     TYPE_INT16 = 0xA0,  // Difference is 16-bit wide
      73             :     TYPE_INT24 = 0xC0,  // Difference is 24-bit wide
      74             :     TYPE_INT32 = 0xE0   // Difference is 32-bit wide
      75             : };
      76             : 
      77             : // Encoding ranges
      78             : GInt32 RANGE_INT4 = 0x00000007L;   // 4-bit
      79             : GInt32 RANGE_INT8 = 0x0000007FL;   // 8-bit
      80             : GInt32 RANGE_INT12 = 0x000007FFL;  // 12-bit
      81             : GInt32 RANGE_INT16 = 0x00007FFFL;  // 16-bit
      82             : GInt32 RANGE_INT24 = 0x007FFFFFL;  // 24-bit
      83             : 
      84             : // Out of range codes
      85             : GInt32 OUT_INT4 = 0xFFFFFFF8;
      86             : GInt32 OUT_INT8 = 0xFFFFFF80;
      87             : GInt32 OUT_INT12 = 0xFFFFF800;
      88             : GInt32 OUT_INT16 = 0xFFFF8000;
      89             : GInt32 OUT_INT24 = 0xFF800000;
      90             : GInt32 OUT_INT32 = 0x80000000;
      91             : 
      92             : constexpr DEMDiffT DIFF_OUI_OF_RANGE = std::numeric_limits<DEMDiffT>::max();
      93             : 
      94             : // Inversion masks
      95             : GInt32 INV_INT4 = 0xFFFFFFF0L;
      96             : GInt32 INV_INT12 = 0xFFFFF000L;
      97             : GInt32 INV_INT24 = 0xFF000000L;
      98             : 
      99             : // Not sure which behavior we wish for int32 overflow, so just do the
     100             : // addition as uint32 to workaround -ftrapv
     101             : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
     102      542772 : static GInt32 AddInt32(GInt32 &nTarget, GInt32 nVal)
     103             : {
     104      542772 :     GUInt32 nTargetU = static_cast<GUInt32>(nTarget);
     105      542772 :     GUInt32 nValU = static_cast<GUInt32>(nVal);
     106      542772 :     nTargetU += nValU;
     107      542772 :     memcpy(&nTarget, &nTargetU, 4);
     108      542772 :     return nTarget;
     109             : }
     110             : 
     111             : /************************************************************************/
     112             : /*                           DEMDecompress()                            */
     113             : /************************************************************************/
     114             : 
     115          18 : size_t RMFDataset::DEMDecompress(const GByte *pabyIn, GUInt32 nSizeIn,
     116             :                                  GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
     117             :                                  GUInt32)
     118             : {
     119          18 :     if (pabyIn == nullptr || pabyOut == nullptr || nSizeOut < nSizeIn ||
     120             :         nSizeIn < 2)
     121           0 :         return 0;
     122             : 
     123          18 :     GInt32 iPrev = 0;  // The last data value decoded.
     124             : 
     125          18 :     const signed char *pabyTempIn =
     126             :         reinterpret_cast<const signed char *>(pabyIn);
     127          18 :     GInt32 *paiOut = reinterpret_cast<GInt32 *>(pabyOut);
     128          18 :     nSizeOut /= sizeof(GInt32);
     129             : 
     130       61662 :     while (nSizeIn > 0)
     131             :     {
     132             :         // Read number of codes in the record and encoding type.
     133       61644 :         GUInt32 nCount = *pabyTempIn & 0x1F;
     134       61644 :         const GUInt32 nType = *pabyTempIn++ & 0xE0;  // The encoding type.
     135       61644 :         nSizeIn--;
     136       61644 :         if (nCount == 0)
     137             :         {
     138        1668 :             if (nSizeIn == 0)
     139           0 :                 break;
     140        1668 :             nCount = 32 + *((GByte *)pabyTempIn++);
     141        1668 :             nSizeIn--;
     142             :         }
     143             : 
     144       61644 :         switch (nType)
     145             :         {
     146       17994 :             case TYPE_ZERO:
     147       17994 :                 if (nSizeOut < nCount)
     148           0 :                     break;
     149       17994 :                 nSizeOut -= nCount;
     150       98978 :                 while (nCount > 0)
     151             :                 {
     152       80984 :                     nCount--;
     153       80984 :                     *paiOut++ = iPrev;
     154             :                 }
     155       17994 :                 break;
     156             : 
     157        1564 :             case TYPE_OUT:
     158        1564 :                 if (nSizeOut < nCount)
     159           0 :                     break;
     160        1564 :                 nSizeOut -= nCount;
     161       26086 :                 while (nCount > 0)
     162             :                 {
     163       24522 :                     nCount--;
     164       24522 :                     *paiOut++ = OUT_INT32;
     165             :                 }
     166        1564 :                 break;
     167             : 
     168        1874 :             case TYPE_INT4:
     169        1874 :                 if (nSizeIn < (nCount + 1) / 2)
     170           0 :                     break;
     171        1874 :                 if (nSizeOut < nCount)
     172           0 :                     break;
     173        1874 :                 nSizeIn -= nCount / 2;
     174        1874 :                 nSizeOut -= nCount;
     175        4902 :                 while (nCount > 0)
     176             :                 {
     177        4014 :                     nCount--;
     178             :                     GInt32 nCode;
     179        4014 :                     nCode = (*pabyTempIn) & 0x0F;
     180        4014 :                     if (nCode > RANGE_INT4)
     181        1752 :                         nCode |= INV_INT4;
     182        4014 :                     *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
     183        3994 :                                                     : AddInt32(iPrev, nCode);
     184             : 
     185        4014 :                     if (nCount == 0)
     186             :                     {
     187         986 :                         if (nSizeIn)
     188             :                         {
     189         986 :                             pabyTempIn++;
     190         986 :                             nSizeIn--;
     191             :                         }
     192         986 :                         break;
     193             :                     }
     194        3028 :                     nCount--;
     195             : 
     196        3028 :                     nCode = ((*pabyTempIn++) >> 4) & 0x0F;
     197        3028 :                     if (nCode > RANGE_INT4)
     198        1222 :                         nCode |= INV_INT4;
     199        6036 :                     *paiOut++ = (nCode == OUT_INT4) ? OUT_INT32
     200        3008 :                                                     : AddInt32(iPrev, nCode);
     201             :                 }
     202        1874 :                 break;
     203             : 
     204        5924 :             case TYPE_INT8:
     205        5924 :                 if (nSizeIn < nCount)
     206           0 :                     break;
     207        5924 :                 if (nSizeOut < nCount)
     208           0 :                     break;
     209        5924 :                 nSizeIn -= nCount;
     210        5924 :                 nSizeOut -= nCount;
     211       50708 :                 while (nCount > 0)
     212             :                 {
     213       44784 :                     nCount--;
     214             :                     GInt32 nCode;
     215       44784 :                     *paiOut++ = ((nCode = *pabyTempIn++) == OUT_INT8)
     216       44784 :                                     ? OUT_INT32
     217       44766 :                                     : AddInt32(iPrev, nCode);
     218             :                 }
     219        5924 :                 break;
     220             : 
     221       15482 :             case TYPE_INT12:
     222       15482 :                 if (nSizeIn < (3 * nCount + 1) / 2)
     223           0 :                     break;
     224       15482 :                 if (nSizeOut < nCount)
     225           0 :                     break;
     226       15482 :                 nSizeIn -= 3 * nCount / 2;
     227       15482 :                 nSizeOut -= nCount;
     228             : 
     229       78758 :                 while (nCount > 0)
     230             :                 {
     231       71274 :                     nCount--;
     232       71274 :                     GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn) & 0x0FFF;
     233       71274 :                     pabyTempIn += 1;
     234       71274 :                     if (nCode > RANGE_INT12)
     235       39394 :                         nCode |= INV_INT12;
     236       71274 :                     *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
     237       70578 :                                                      : AddInt32(iPrev, nCode);
     238             : 
     239       71274 :                     if (nCount == 0)
     240             :                     {
     241        7998 :                         if (nSizeIn)
     242             :                         {
     243        7998 :                             pabyTempIn++;
     244        7998 :                             nSizeIn--;
     245             :                         }
     246        7998 :                         break;
     247             :                     }
     248       63276 :                     nCount--;
     249             : 
     250       63276 :                     nCode = (CPL_LSBSINT16PTR(pabyTempIn) >> 4) & 0x0FFF;
     251       63276 :                     pabyTempIn += 2;
     252       63276 :                     if (nCode > RANGE_INT12)
     253       35672 :                         nCode |= INV_INT12;
     254      125870 :                     *paiOut++ = (nCode == OUT_INT12) ? OUT_INT32
     255       62594 :                                                      : AddInt32(iPrev, nCode);
     256             :                 }
     257       15482 :                 break;
     258             : 
     259       17958 :             case TYPE_INT16:
     260       17958 :                 if (nSizeIn < 2 * nCount)
     261           0 :                     break;
     262       17958 :                 if (nSizeOut < nCount)
     263           0 :                     break;
     264       17958 :                 nSizeIn -= 2 * nCount;
     265       17958 :                 nSizeOut -= nCount;
     266             : 
     267      263522 :                 while (nCount > 0)
     268             :                 {
     269      245564 :                     nCount--;
     270      245564 :                     const GInt32 nCode = CPL_LSBSINT16PTR(pabyTempIn);
     271      245564 :                     pabyTempIn += 2;
     272      485978 :                     *paiOut++ = (nCode == OUT_INT16) ? OUT_INT32
     273      240414 :                                                      : AddInt32(iPrev, nCode);
     274             :                 }
     275       17958 :                 break;
     276             : 
     277         676 :             case TYPE_INT24:
     278         676 :                 if (nSizeIn < 3 * nCount)
     279           0 :                     break;
     280         676 :                 if (nSizeOut < nCount)
     281           0 :                     break;
     282         676 :                 nSizeIn -= 3 * nCount;
     283         676 :                 nSizeOut -= nCount;
     284             : 
     285       70290 :                 while (nCount > 0)
     286             :                 {
     287       69614 :                     nCount--;
     288       69614 :                     GInt32 nCode = (*(GByte *)pabyTempIn) |
     289       69614 :                                    ((*(GByte *)(pabyTempIn + 1)) << 8) |
     290       69614 :                                    ((*(GByte *)(pabyTempIn + 2)) << 16);
     291       69614 :                     pabyTempIn += 3;
     292       69614 :                     if (nCode > RANGE_INT24)
     293       31998 :                         nCode |= INV_INT24;
     294      137972 :                     *paiOut++ = (nCode == OUT_INT24) ? OUT_INT32
     295       68358 :                                                      : AddInt32(iPrev, nCode);
     296             :                 }
     297         676 :                 break;
     298             : 
     299         172 :             case TYPE_INT32:
     300         172 :                 if (nSizeIn < 4 * nCount)
     301           0 :                     break;
     302         172 :                 if (nSizeOut < nCount)
     303           0 :                     break;
     304         172 :                 nSizeIn -= 4 * nCount;
     305         172 :                 nSizeOut -= nCount;
     306             : 
     307       49232 :                 while (nCount > 0)
     308             :                 {
     309       49060 :                     nCount--;
     310       49060 :                     GInt32 nCode = CPL_LSBSINT32PTR(pabyTempIn);
     311       49060 :                     pabyTempIn += 4;
     312       98120 :                     *paiOut++ = (nCode == OUT_INT32) ? OUT_INT32
     313       49060 :                                                      : AddInt32(iPrev, nCode);
     314             :                 }
     315         172 :                 break;
     316             :         }
     317             :     }
     318             : 
     319          18 :     return (GByte *)paiOut - pabyOut;
     320             : }
     321             : 
     322             : /************************************************************************/
     323             : /*                            DEMWriteCode()                            */
     324             : /************************************************************************/
     325             : 
     326        1212 : static CPLErr DEMWriteRecord(const DEMDiffT *paiRecord, RmfTypes eRecordType,
     327             :                              GUInt32 nRecordSize, GInt32 nSizeOut,
     328             :                              GByte *&pabyCurrent)
     329             : {
     330        1212 :     const GUInt32 nMaxCountInHeader = 31;
     331             :     GInt32 iCode;
     332             :     GInt32 iPrevCode;
     333             : 
     334        1212 :     if (nRecordSize <= nMaxCountInHeader)
     335             :     {
     336         481 :         nSizeOut -= 1;
     337         481 :         if (nSizeOut <= 0)
     338             :         {
     339           0 :             return CE_Failure;
     340             :         }
     341             : 
     342         481 :         *pabyCurrent++ = static_cast<GByte>(eRecordType | nRecordSize);
     343             :     }
     344             :     else
     345             :     {
     346         731 :         nSizeOut -= 2;
     347         731 :         if (nSizeOut <= 0)
     348             :         {
     349           0 :             return CE_Failure;
     350             :         }
     351             : 
     352         731 :         *pabyCurrent++ = static_cast<GByte>(eRecordType);
     353         731 :         *pabyCurrent++ = static_cast<GByte>(nRecordSize - 32);
     354             :     }
     355             : 
     356        1212 :     switch (eRecordType)
     357             :     {
     358          46 :         case TYPE_INT4:
     359          46 :             nSizeOut -= ((nRecordSize + 1) / 2);
     360          46 :             if (nSizeOut <= 0)
     361             :             {
     362           0 :                 return CE_Failure;
     363             :             }
     364             : 
     365          84 :             for (GUInt32 n = 0; n != nRecordSize; ++n)
     366             :             {
     367          68 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     368             :                 {
     369           0 :                     iCode = OUT_INT4;
     370             :                 }
     371             :                 else
     372             :                 {
     373          68 :                     iCode = static_cast<GInt32>(paiRecord[n]);
     374             :                 }
     375          68 :                 *pabyCurrent = static_cast<GByte>(iCode & 0x0F);
     376             : 
     377          68 :                 ++n;
     378          68 :                 if (n == nRecordSize)
     379             :                 {
     380          30 :                     pabyCurrent++;
     381          30 :                     break;
     382             :                 }
     383             : 
     384          38 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     385             :                 {
     386           0 :                     iCode = OUT_INT4;
     387             :                 }
     388             :                 else
     389             :                 {
     390          38 :                     iCode = static_cast<GInt32>(paiRecord[n]);
     391             :                 }
     392          38 :                 *pabyCurrent++ |= static_cast<GByte>((iCode & 0x0F) << 4);
     393             :             }
     394          46 :             break;
     395             : 
     396         100 :         case TYPE_INT8:
     397         100 :             nSizeOut -= nRecordSize;
     398         100 :             if (nSizeOut <= 0)
     399             :             {
     400           0 :                 return CE_Failure;
     401             :             }
     402             : 
     403        8708 :             for (GUInt32 n = 0; n != nRecordSize; ++n)
     404             :             {
     405        8608 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     406             :                 {
     407           9 :                     *pabyCurrent++ = static_cast<GByte>(OUT_INT8);
     408             :                 }
     409             :                 else
     410             :                 {
     411        8599 :                     *pabyCurrent++ = static_cast<GByte>(paiRecord[n]);
     412             :                 }
     413             :             }
     414         100 :             break;
     415             : 
     416         278 :         case TYPE_INT12:
     417         278 :             nSizeOut -= ((nRecordSize * 3 + 1) / 2);
     418         278 :             if (nSizeOut <= 0)
     419             :             {
     420           0 :                 return CE_Failure;
     421             :             }
     422             : 
     423        6851 :             for (GUInt32 n = 0; n != nRecordSize; ++n)
     424             :             {
     425        6744 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     426             :                 {
     427         348 :                     iCode = OUT_INT12;
     428             :                 }
     429             :                 else
     430             :                 {
     431        6396 :                     iCode = static_cast<GInt32>(paiRecord[n]);
     432             :                 }
     433             : 
     434        6744 :                 iPrevCode = iCode;
     435        6744 :                 *pabyCurrent++ = static_cast<GByte>(iCode & 0x00FF);
     436             : 
     437        6744 :                 ++n;
     438        6744 :                 if (n == nRecordSize)
     439             :                 {
     440         171 :                     *pabyCurrent++ =
     441         171 :                         static_cast<GByte>((iPrevCode & 0x0F00) >> 8);
     442         171 :                     break;
     443             :                 }
     444             : 
     445        6573 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     446             :                 {
     447         341 :                     iCode = OUT_INT12;
     448             :                 }
     449             :                 else
     450             :                 {
     451        6232 :                     iCode = static_cast<GInt32>(paiRecord[n]);
     452             :                 }
     453        6573 :                 iCode = (((iPrevCode & 0x0F00) >> 8) | ((iCode & 0x0FFF) << 4));
     454             : 
     455        6573 :                 CPL_LSBPTR32(&iCode);
     456        6573 :                 memcpy(pabyCurrent, &iCode, 2);
     457        6573 :                 pabyCurrent += 2;
     458             :             }
     459         278 :             break;
     460             : 
     461         395 :         case TYPE_INT16:
     462         395 :             nSizeOut -= (nRecordSize * 2);
     463         395 :             if (nSizeOut <= 0)
     464             :             {
     465           0 :                 return CE_Failure;
     466             :             }
     467             : 
     468      103286 :             for (GUInt32 n = 0; n != nRecordSize; ++n)
     469             :             {
     470      102891 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     471             :                 {
     472        2575 :                     iCode = OUT_INT16;
     473             :                 }
     474             :                 else
     475             :                 {
     476      100316 :                     iCode = static_cast<GInt32>(paiRecord[n]);
     477             :                 }
     478      102891 :                 CPL_LSBPTR32(&iCode);
     479      102891 :                 memcpy(pabyCurrent, &iCode, 2);
     480      102891 :                 pabyCurrent += 2;
     481             :             }
     482         395 :             break;
     483             : 
     484         137 :         case TYPE_INT24:
     485         137 :             nSizeOut -= (nRecordSize * 3);
     486         137 :             if (nSizeOut <= 0)
     487             :             {
     488           0 :                 return CE_Failure;
     489             :             }
     490             : 
     491       34743 :             for (GUInt32 n = 0; n != nRecordSize; ++n)
     492             :             {
     493       34606 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     494             :                 {
     495         628 :                     iCode = OUT_INT24;
     496             :                 }
     497             :                 else
     498             :                 {
     499       33978 :                     iCode = static_cast<GInt32>(paiRecord[n]);
     500             :                 }
     501       34606 :                 CPL_LSBPTR32(&iCode);
     502       34606 :                 memcpy(pabyCurrent, &iCode, 3);
     503       34606 :                 pabyCurrent += 3;
     504             :             }
     505         137 :             break;
     506             : 
     507          86 :         case TYPE_INT32:
     508          86 :             nSizeOut -= (nRecordSize * 4);
     509          86 :             if (nSizeOut <= 0)
     510             :             {
     511           0 :                 return CE_Failure;
     512             :             }
     513             : 
     514       24616 :             for (GUInt32 n = 0; n != nRecordSize; ++n)
     515             :             {
     516       24530 :                 if (paiRecord[n] == DIFF_OUI_OF_RANGE)
     517             :                 {
     518           0 :                     iCode = OUT_INT32;
     519             :                 }
     520             :                 else
     521             :                 {
     522       24530 :                     iCode = static_cast<GInt32>(paiRecord[n]);
     523             :                 }
     524       24530 :                 CPL_LSBPTR32(&iCode);
     525       24530 :                 memcpy(pabyCurrent, &iCode, 4);
     526       24530 :                 pabyCurrent += 4;
     527             :             }
     528          86 :             break;
     529             : 
     530         170 :         case TYPE_ZERO:
     531             :         case TYPE_OUT:
     532         170 :             break;
     533             : 
     534           0 :         default:
     535           0 :             return CE_Failure;
     536             :     }
     537             : 
     538        1212 :     return CE_None;
     539             : }
     540             : 
     541             : /************************************************************************/
     542             : /*                             DEMDeltaType()                           */
     543             : /************************************************************************/
     544             : 
     545      189311 : static RmfTypes DEMDeltaType(DEMDiffT delta)
     546             : {
     547      189311 :     if (delta <= RANGE_INT12)
     548             :     {
     549      141083 :         if (delta <= RANGE_INT4)
     550             :         {
     551       61786 :             if (delta == 0)
     552             :             {
     553       49823 :                 return TYPE_ZERO;
     554             :             }
     555             :             else
     556             :             {
     557       11963 :                 return TYPE_INT4;
     558             :             }
     559             :         }
     560             :         else
     561             :         {
     562       79297 :             if (delta <= RANGE_INT8)
     563             :             {
     564       23225 :                 return TYPE_INT8;
     565             :             }
     566             :             else
     567             :             {
     568       56072 :                 return TYPE_INT12;
     569             :             }
     570             :         }
     571             :     }
     572             :     else
     573             :     {
     574       48228 :         if (delta <= RANGE_INT24)
     575             :         {
     576       33338 :             if (delta <= RANGE_INT16)
     577             :             {
     578       24341 :                 return TYPE_INT16;
     579             :             }
     580             :             else
     581             :             {
     582        8997 :                 return TYPE_INT24;
     583             :             }
     584             :         }
     585             :         else
     586             :         {
     587       14890 :             return TYPE_INT32;
     588             :         }
     589             :     }
     590             : }
     591             : 
     592             : /************************************************************************/
     593             : /*                             DEMCompress()                            */
     594             : /************************************************************************/
     595             : 
     596           5 : size_t RMFDataset::DEMCompress(const GByte *pabyIn, GUInt32 nSizeIn,
     597             :                                GByte *pabyOut, GUInt32 nSizeOut, GUInt32,
     598             :                                GUInt32, const RMFDataset *poDS)
     599             : {
     600           5 :     if (pabyIn == nullptr || pabyOut == nullptr || nSizeIn < sizeof(DEMWorkT))
     601           0 :         return 0;
     602             : 
     603           5 :     const GUInt32 anDeltaTypeSize[8] = {0, 0, 4, 8, 12, 16, 24, 32};
     604           5 :     const GUInt32 nMaxRecordSize = 255 + 32;
     605             : 
     606           5 :     DEMWorkT iMin(std::numeric_limits<DEMWorkT>::min() + 1);
     607           5 :     if (poDS != nullptr &&
     608           5 :         poDS->sHeader.adfElevMinMax[0] < poDS->sHeader.adfElevMinMax[1])
     609             :     {
     610           0 :         iMin = static_cast<DEMWorkT>(poDS->sHeader.adfElevMinMax[0]);
     611             :     }
     612           5 :     GUInt32 nLessCount = 0;
     613           5 :     GUInt32 nRecordSize = 0;
     614           5 :     RmfTypes eRecordType = TYPE_OUT;
     615           5 :     DEMDiffT aiRecord[nMaxRecordSize] = {0};
     616           5 :     DEMWorkT aiPrev[nMaxRecordSize] = {0};
     617             : 
     618           5 :     GByte *pabyCurrent = pabyOut;
     619           5 :     DEMWorkT iPrev = 0;
     620             : 
     621           5 :     nSizeIn = nSizeIn / sizeof(DEMWorkT);
     622             : 
     623           5 :     const DEMWorkT *paiIn = reinterpret_cast<const DEMWorkT *>(pabyIn);
     624           5 :     const DEMWorkT *paiInEnd = paiIn + nSizeIn;
     625             : 
     626             :     while (true)
     627             :     {
     628      197413 :         GUInt32 nRecordElementSize = 0;
     629             : 
     630      197413 :         if (paiIn >= paiInEnd)
     631             :         {
     632          10 :             if (nRecordSize == 0)
     633             :             {
     634           5 :                 return pabyCurrent - pabyOut;
     635             :             }
     636             : 
     637           5 :             if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
     638             :                                           nSizeOut, pabyCurrent))
     639             :             {
     640           0 :                 return 0;
     641             :             }
     642           5 :             nRecordSize = 0;
     643           5 :             continue;
     644             :         }
     645             : 
     646      197403 :         DEMWorkT iCurr = *(paiIn++);
     647             :         RmfTypes eCurrType;
     648             : 
     649      197403 :         if (iCurr < iMin)
     650             :         {
     651        8092 :             eCurrType = TYPE_OUT;
     652        8092 :             aiRecord[nRecordSize] = DIFF_OUI_OF_RANGE;
     653        8092 :             aiPrev[nRecordSize] = iPrev;
     654             :         }
     655             :         else
     656             :         {
     657      189311 :             DEMDiffT delta =
     658      189311 :                 static_cast<DEMDiffT>(iCurr) - static_cast<DEMDiffT>(iPrev);
     659             : 
     660      189311 :             aiRecord[nRecordSize] = delta;
     661      189311 :             aiPrev[nRecordSize] = iCurr;
     662             : 
     663      189311 :             if (delta < 0)
     664       79880 :                 delta = -delta;
     665             : 
     666      189311 :             eCurrType = DEMDeltaType(delta);
     667      189311 :             iPrev = iCurr;
     668             :         }
     669      197403 :         nRecordSize++;
     670             : 
     671      197403 :         if (nRecordSize == 1)
     672             :         {
     673        1212 :             eRecordType = eCurrType;
     674             :             // nRecordElementSize = anDeltaTypeSize[eCurrType >> 5];
     675        1212 :             continue;
     676             :         }
     677             : 
     678      196191 :         if (nRecordSize == nMaxRecordSize)
     679             :         {
     680         602 :             nLessCount = 0;
     681         602 :             if (CE_None != DEMWriteRecord(aiRecord, eRecordType, nRecordSize,
     682             :                                           nSizeOut, pabyCurrent))
     683             :             {
     684           0 :                 return 0;
     685             :             }
     686         602 :             iPrev = aiPrev[nRecordSize - 1];
     687         602 :             nRecordSize = 0;
     688         602 :             continue;
     689             :         }
     690             : 
     691      195589 :         if (eCurrType == eRecordType)
     692             :         {
     693       59166 :             nLessCount = 0;
     694       59166 :             continue;
     695             :         }
     696             : 
     697      136423 :         if ((eCurrType > eRecordType) || (eCurrType | eRecordType) == TYPE_ZERO)
     698             :         {
     699         605 :             --paiIn;
     700         605 :             if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
     701             :                                           nRecordSize - 1, nSizeOut,
     702             :                                           pabyCurrent))
     703             :             {
     704           0 :                 return 0;
     705             :             }
     706         605 :             iPrev = aiPrev[nRecordSize - 2];
     707         605 :             nRecordSize = 0;
     708         605 :             nLessCount = 0;
     709         605 :             continue;
     710             :         }
     711             : 
     712      135818 :         nLessCount++;
     713             : 
     714      135818 :         GUInt32 nDeltaSize(anDeltaTypeSize[eCurrType >> 5]);
     715      135818 :         if (nRecordElementSize < nDeltaSize ||
     716       45035 :             (nRecordElementSize - nDeltaSize) * nLessCount < 16)
     717             :         {
     718      135818 :             continue;
     719             :         }
     720             : 
     721           0 :         paiIn -= nLessCount;
     722           0 :         if (CE_None != DEMWriteRecord(aiRecord, eRecordType,
     723             :                                       nRecordSize - nLessCount, nSizeOut,
     724             :                                       pabyCurrent))
     725             :         {
     726           0 :             return 0;
     727             :         }
     728           0 :         iPrev = aiPrev[nRecordSize - nLessCount - 1];
     729           0 :         nRecordSize = 0;
     730           0 :         nLessCount = 0;
     731      197408 :     }
     732             : 
     733             :     return 0;
     734             : }

Generated by: LCOV version 1.14