LCOV - code coverage report
Current view: directory - frmts/rmf - rmfdem.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 114 0 0.0 %
Date: 2012-04-28 Functions: 1 0 0.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: rmflzw.cpp 11865 2007-08-09 11:53:57Z warmerdam $
       3                 :  *
       4                 :  * Project:  Raster Matrix Format
       5                 :  * Purpose:  Implementation of the ad-hoc compression algorithm used in
       6                 :  *           GIS "Panorama"/"Integratsia".
       7                 :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2009, Andrey Kiselev <dron@ak4719.spb.edu>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "cpl_conv.h"
      32                 : 
      33                 : #include "rmfdataset.h"
      34                 : 
      35                 : /*
      36                 :  * The encoded data stream is a series of records.
      37                 :  *
      38                 :  * Encoded record consist from the 1-byte record header followed by the
      39                 :  * encoded data block. Header specifies the number of elements in the data
      40                 :  * block and encoding type. Header format
      41                 :  *
      42                 :  * +---+---+---+---+---+---+---+---+
      43                 :  * |   type    |       count       |
      44                 :  * +---+---+---+---+---+---+---+---+
      45                 :  *   7   6   5   4   3   2   1   0
      46                 :  *
      47                 :  * If count is zero then it means that there are more than 31 elements in this
      48                 :  * record. Read the next byte in the stream and increase its value with 32 to
      49                 :  * get the count. In this case maximum number of elements is 287.
      50                 :  *
      51                 :  * The "type" field specifies encoding type. It can be either difference
      52                 :  * between the previous and the next data value (for the first element the
      53                 :  * previous value is zero) or out-of-range codes.
      54                 :  *
      55                 :  * In case of "out of range" or "zero difference" values there are no more
      56                 :  * elements in record after the header. Otherwise read as much encoded
      57                 :  * elements as count specifies.
      58                 :  */
      59                 : 
      60                 : // Encoding types
      61                 : #define TYPE_OUT    0x00    // Value is out of range
      62                 : #define TYPE_ZERO   0x20    // Zero difference
      63                 : #define TYPE_INT4   0x40    // Difference is 4-bit wide
      64                 : #define TYPE_INT8   0x60    // Difference is 8-bit wide
      65                 : #define TYPE_INT12  0x80    // Difference is 12-bit wide
      66                 : #define TYPE_INT16  0xA0    // Difference is 16-bit wide
      67                 : #define TYPE_INT24  0xC0    // Difference is 24-bit wide
      68                 : #define TYPE_INT32  0xE0    // Difference is 32-bit wide
      69                 : 
      70                 : // Encoding ranges
      71                 : #define RANGE_INT4  0x00000007L    // 4-bit
      72                 : #define RANGE_INT12 0x000007FFL    // 12-bit
      73                 : #define RANGE_INT24 0x007FFFFFL    // 24-bit
      74                 : 
      75                 : // Out of range codes
      76                 : #define OUT_INT4    ((GInt32)0xFFFFFFF8)
      77                 : #define OUT_INT8    ((GInt32)0xFFFFFF80)
      78                 : #define OUT_INT12   ((GInt32)0xFFFFF800)
      79                 : #define OUT_INT16   ((GInt32)0xFFFF8000)
      80                 : #define OUT_INT24   ((GInt32)0xFF800000)
      81                 : #define OUT_INT32   ((GInt32)0x80000000)
      82                 : 
      83                 : // Inversion masks
      84                 : #define INV_INT4    0xFFFFFFF0L
      85                 : #define INV_INT12   0xFFFFF000L
      86                 : #define INV_INT24   0xFF000000L
      87                 : 
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                           DEMDecompress()                            */
      91                 : /************************************************************************/
      92                 : 
      93               0 : int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
      94                 :                                GByte* pabyOut, GUInt32 nSizeOut )
      95                 : {
      96                 :     GUInt32 nCount;             // Number of encoded data elements to read
      97                 :     char* pabyTempIn;
      98                 :     GInt32* paiOut;
      99                 :     GInt32 nType;               // The encoding type
     100               0 :     GInt32 iPrev = 0;           // The last data value decoded
     101                 :     GInt32 nCode;
     102                 : 
     103               0 :     if ( pabyIn == 0 ||
     104                 :          pabyOut == 0 ||
     105                 :          nSizeOut < nSizeIn ||
     106                 :          nSizeIn < 2 )
     107               0 :         return 0;
     108                 : 
     109               0 :     pabyTempIn  = (char*)pabyIn;
     110               0 :     paiOut = (GInt32*)pabyOut;
     111               0 :     nSizeOut /= sizeof(GInt32);
     112                 : 
     113               0 :     while ( nSizeIn > 0 )
     114                 :     {
     115                 :         // Read number of codes in the record and encoding type
     116               0 :         nCount = *pabyTempIn & 0x1F;
     117               0 :         nType = *pabyTempIn++ & 0xE0;
     118               0 :         nSizeIn--;
     119               0 :         if ( nCount == 0 )
     120                 :         {
     121               0 :             if ( nSizeIn == 0 )
     122               0 :                 break;
     123               0 :             nCount = 32 + *((unsigned char*)pabyTempIn++);
     124               0 :             nSizeIn--;
     125                 :         }
     126                 : 
     127               0 :         switch (nType)
     128                 :         {
     129                 :             case TYPE_ZERO:
     130               0 :                 if ( nSizeOut < nCount )
     131               0 :                     break;
     132               0 :                 nSizeOut -= nCount;
     133               0 :                 while ( nCount-- > 0 )
     134               0 :                     *paiOut++ = iPrev;
     135               0 :                 break;
     136                 : 
     137                 :             case TYPE_OUT:
     138               0 :                 if ( nSizeOut < nCount )
     139               0 :                     break;
     140               0 :                 nSizeOut -= nCount;
     141               0 :                 while ( nCount-- > 0 )
     142               0 :                     *paiOut++ = OUT_INT32;
     143               0 :                 break;
     144                 : 
     145                 :             case TYPE_INT4:
     146               0 :                 if ( nSizeIn < nCount / 2 )
     147               0 :                     break;
     148               0 :                 if ( nSizeOut < nCount )
     149               0 :                     break;
     150               0 :                 nSizeIn -= nCount / 2;
     151               0 :                 nSizeOut -= nCount;
     152               0 :                 while ( nCount-- > 0 )
     153                 :                 {
     154               0 :                     nCode = (*pabyTempIn) & 0x0F;
     155               0 :                     if ( nCode > RANGE_INT4 )
     156               0 :                         nCode |= INV_INT4;
     157                 :                     *paiOut++ = ( nCode == OUT_INT4 ) ?
     158               0 :                         OUT_INT32 : iPrev += nCode;
     159                 : 
     160               0 :                     if ( nCount-- == 0 )
     161                 :                     {
     162               0 :                         pabyTempIn++;
     163               0 :                         nSizeIn--;
     164               0 :                         break;
     165                 :                     }
     166                 : 
     167               0 :                     nCode = ((*pabyTempIn++)>>4) & 0x0F;
     168               0 :                     if ( nCode > RANGE_INT4 )
     169               0 :                         nCode |= INV_INT4;
     170                 :                     *paiOut++ = ( nCode == OUT_INT4 ) ?
     171               0 :                         OUT_INT32 : iPrev += nCode;
     172                 :                 }
     173               0 :                 break;
     174                 : 
     175                 :             case TYPE_INT8:
     176               0 :                 if ( nSizeIn < nCount )
     177               0 :                     break;
     178               0 :                 if ( nSizeOut < nCount )
     179               0 :                     break;
     180               0 :                 nSizeIn -= nCount;
     181               0 :                 nSizeOut -= nCount;
     182               0 :                 while ( nCount-- > 0 )
     183                 :                 {
     184                 :                     *paiOut++ = ( (nCode = *pabyTempIn++) == OUT_INT8 ) ?
     185               0 :                         OUT_INT32 : iPrev += nCode;
     186                 :                 }
     187               0 :                 break;
     188                 : 
     189                 :             case TYPE_INT12:
     190               0 :                 if ( nSizeIn < 3 * nCount / 2 )
     191               0 :                     break;
     192               0 :                 if ( nSizeOut < nCount )
     193               0 :                     break;
     194               0 :                 nSizeIn -= 3 * nCount / 2;
     195               0 :                 nSizeOut -= nCount;
     196                 : 
     197               0 :                 while ( nCount-- > 0 )
     198                 :                 {
     199               0 :                     nCode = *((GInt16*)pabyTempIn++) & 0x0FFF;
     200               0 :                     if ( nCode > RANGE_INT12 )
     201               0 :                         nCode |= INV_INT12;
     202                 :                     *paiOut++ = ( nCode == OUT_INT12 ) ?
     203               0 :                         OUT_INT32 : iPrev += nCode;
     204                 : 
     205               0 :                     if ( nCount-- == 0 )
     206                 :                     {
     207               0 :                         pabyTempIn++;
     208               0 :                         nSizeIn--;
     209               0 :                         break;
     210                 :                     }
     211                 : 
     212               0 :                     nCode = ( (*(GInt16*)pabyTempIn) >> 4 ) & 0x0FFF;
     213               0 :                     pabyTempIn += 2;
     214               0 :                     if ( nCode > RANGE_INT12 )
     215               0 :                         nCode |= INV_INT12;
     216                 :                     *paiOut++ = ( nCode == OUT_INT12 ) ?
     217               0 :                         OUT_INT32 : iPrev += nCode;
     218                 :                 }
     219               0 :                 break;
     220                 : 
     221                 :             case TYPE_INT16:
     222               0 :                 if ( nSizeIn < 2 * nCount )
     223               0 :                     break;
     224               0 :                 if ( nSizeOut < nCount )
     225               0 :                     break;
     226               0 :                 nSizeIn -= 2 * nCount;
     227               0 :                 nSizeOut -= nCount;
     228                 : 
     229               0 :                 while ( nCount-- > 0 )
     230                 :                 {
     231               0 :                     nCode = *((GInt16*)pabyTempIn);
     232               0 :                     pabyTempIn += 2;
     233                 :                     *paiOut++ = ( nCode == OUT_INT16 ) ?
     234               0 :                         OUT_INT32 : iPrev += nCode;
     235                 :                 }
     236               0 :                 break;
     237                 : 
     238                 :             case TYPE_INT24:
     239               0 :                 if ( nSizeIn < 3 * nCount )
     240               0 :                     break;
     241               0 :                 if ( nSizeOut < nCount )
     242               0 :                     break;
     243               0 :                 nSizeIn -= 3 * nCount;
     244               0 :                 nSizeOut -= nCount;
     245                 : 
     246               0 :                 while ( nCount-- > 0 )
     247                 :                 {
     248               0 :                     nCode =*((GInt32 *)pabyTempIn) & 0x0FFF;
     249               0 :                     pabyTempIn += 3;
     250               0 :                     if ( nCode > RANGE_INT24 )
     251               0 :                         nCode |= INV_INT24;
     252                 :                     *paiOut++ = ( nCode == OUT_INT24 ) ?
     253               0 :                         OUT_INT32 : iPrev += nCode;
     254                 :                 }
     255               0 :                 break;
     256                 : 
     257                 :             case TYPE_INT32:
     258               0 :                 if ( nSizeIn < 4 * nCount )
     259               0 :                     break;
     260               0 :                 if ( nSizeOut < nCount )
     261               0 :                     break;
     262               0 :                 nSizeIn -= 4 * nCount;
     263               0 :                 nSizeOut -= nCount;
     264                 : 
     265               0 :                 while ( nCount-- > 0 )
     266                 :                 {
     267               0 :                     nCode = *(GInt32 *)pabyTempIn;
     268               0 :                     pabyTempIn += 4;
     269                 :                     *paiOut++ = ( nCode == OUT_INT32 ) ?
     270               0 :                         OUT_INT32 : iPrev += nCode;
     271                 :                 }
     272                 :                 break;
     273                 :     }
     274                 :   }
     275                 : 
     276               0 :   return ((GByte*)paiOut - pabyOut);
     277                 : }
     278                 : 

Generated by: LCOV version 1.7