~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to frmts/rmf/rmfdem.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
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
    GInt32 iPrev = 0;           // The last data value decoded
 
101
    GInt32 nCode;
 
102
 
 
103
    if ( pabyIn == 0 ||
 
104
         pabyOut == 0 ||
 
105
         nSizeOut < nSizeIn ||
 
106
         nSizeIn < 2 )
 
107
        return 0;
 
108
 
 
109
    pabyTempIn  = (char*)pabyIn;
 
110
    paiOut = (GInt32*)pabyOut;
 
111
    nSizeOut /= sizeof(GInt32);
 
112
 
 
113
    while ( nSizeIn > 0 )
 
114
    {
 
115
        // Read number of codes in the record and encoding type
 
116
        nCount = *pabyTempIn & 0x1F;
 
117
        nType = *pabyTempIn++ & 0xE0;
 
118
        nSizeIn--;
 
119
        if ( nCount == 0 )
 
120
        {
 
121
            if ( nSizeIn == 0 )
 
122
                break;
 
123
            nCount = 32 + *((unsigned char*)pabyTempIn++);
 
124
            nSizeIn--;
 
125
        }
 
126
 
 
127
        switch (nType)
 
128
        {
 
129
            case TYPE_ZERO:
 
130
                if ( nSizeOut < nCount )
 
131
                    break;
 
132
                nSizeOut -= nCount;
 
133
                while ( nCount-- > 0 )
 
134
                    *paiOut++ = iPrev;
 
135
                break;
 
136
 
 
137
            case TYPE_OUT:
 
138
                if ( nSizeOut < nCount )
 
139
                    break;
 
140
                nSizeOut -= nCount;
 
141
                while ( nCount-- > 0 )
 
142
                    *paiOut++ = OUT_INT32;
 
143
                break;
 
144
 
 
145
            case TYPE_INT4:
 
146
                if ( nSizeIn < nCount / 2 )
 
147
                    break;
 
148
                if ( nSizeOut < nCount )
 
149
                    break;
 
150
                nSizeIn -= nCount / 2;
 
151
                nSizeOut -= nCount;
 
152
                while ( nCount-- > 0 )
 
153
                {
 
154
                    nCode = (*pabyTempIn) & 0x0F;
 
155
                    if ( nCode > RANGE_INT4 )
 
156
                        nCode |= INV_INT4;
 
157
                    *paiOut++ = ( nCode == OUT_INT4 ) ?
 
158
                        OUT_INT32 : iPrev += nCode;
 
159
 
 
160
                    if ( nCount-- == 0 )
 
161
                    {
 
162
                        pabyTempIn++;
 
163
                        nSizeIn--;
 
164
                        break;
 
165
                    }
 
166
 
 
167
                    nCode = ((*pabyTempIn++)>>4) & 0x0F;
 
168
                    if ( nCode > RANGE_INT4 )
 
169
                        nCode |= INV_INT4;
 
170
                    *paiOut++ = ( nCode == OUT_INT4 ) ?
 
171
                        OUT_INT32 : iPrev += nCode;
 
172
                }
 
173
                break;
 
174
 
 
175
            case TYPE_INT8:
 
176
                if ( nSizeIn < nCount )
 
177
                    break;
 
178
                if ( nSizeOut < nCount )
 
179
                    break;
 
180
                nSizeIn -= nCount;
 
181
                nSizeOut -= nCount;
 
182
                while ( nCount-- > 0 )
 
183
                {
 
184
                    *paiOut++ = ( (nCode = *pabyTempIn++) == OUT_INT8 ) ?
 
185
                        OUT_INT32 : iPrev += nCode;
 
186
                }
 
187
                break;
 
188
 
 
189
            case TYPE_INT12:
 
190
                if ( nSizeIn < 3 * nCount / 2 )
 
191
                    break;
 
192
                if ( nSizeOut < nCount )
 
193
                    break;
 
194
                nSizeIn -= 3 * nCount / 2;
 
195
                nSizeOut -= nCount;
 
196
 
 
197
                while ( nCount-- > 0 )
 
198
                {
 
199
                    nCode = *((GInt16*)pabyTempIn++) & 0x0FFF;
 
200
                    if ( nCode > RANGE_INT12 )
 
201
                        nCode |= INV_INT12;
 
202
                    *paiOut++ = ( nCode == OUT_INT12 ) ?
 
203
                        OUT_INT32 : iPrev += nCode;
 
204
 
 
205
                    if ( nCount-- == 0 )
 
206
                    {
 
207
                        pabyTempIn++;
 
208
                        nSizeIn--;
 
209
                        break;
 
210
                    }
 
211
 
 
212
                    nCode = ( (*(GInt16*)pabyTempIn) >> 4 ) & 0x0FFF;
 
213
                    pabyTempIn += 2;
 
214
                    if ( nCode > RANGE_INT12 )
 
215
                        nCode |= INV_INT12;
 
216
                    *paiOut++ = ( nCode == OUT_INT12 ) ?
 
217
                        OUT_INT32 : iPrev += nCode;
 
218
                }
 
219
                break;
 
220
 
 
221
            case TYPE_INT16:
 
222
                if ( nSizeIn < 2 * nCount )
 
223
                    break;
 
224
                if ( nSizeOut < nCount )
 
225
                    break;
 
226
                nSizeIn -= 2 * nCount;
 
227
                nSizeOut -= nCount;
 
228
 
 
229
                while ( nCount-- > 0 )
 
230
                {
 
231
                    nCode = *((GInt16*)pabyTempIn);
 
232
                    pabyTempIn += 2;
 
233
                    *paiOut++ = ( nCode == OUT_INT16 ) ?
 
234
                        OUT_INT32 : iPrev += nCode;
 
235
                }
 
236
                break;
 
237
 
 
238
            case TYPE_INT24:
 
239
                if ( nSizeIn < 3 * nCount )
 
240
                    break;
 
241
                if ( nSizeOut < nCount )
 
242
                    break;
 
243
                nSizeIn -= 3 * nCount;
 
244
                nSizeOut -= nCount;
 
245
 
 
246
                while ( nCount-- > 0 )
 
247
                {
 
248
                    nCode =*((GInt32 *)pabyTempIn) & 0x0FFF;
 
249
                    pabyTempIn += 3;
 
250
                    if ( nCode > RANGE_INT24 )
 
251
                        nCode |= INV_INT24;
 
252
                    *paiOut++ = ( nCode == OUT_INT24 ) ?
 
253
                        OUT_INT32 : iPrev += nCode;
 
254
                }
 
255
                break;
 
256
 
 
257
            case TYPE_INT32:
 
258
                if ( nSizeIn < 4 * nCount )
 
259
                    break;
 
260
                if ( nSizeOut < nCount )
 
261
                    break;
 
262
                nSizeIn -= 4 * nCount;
 
263
                nSizeOut -= nCount;
 
264
 
 
265
                while ( nCount-- > 0 )
 
266
                {
 
267
                    nCode = *(GInt32 *)pabyTempIn;
 
268
                    pabyTempIn += 4;
 
269
                    *paiOut++ = ( nCode == OUT_INT32 ) ?
 
270
                        OUT_INT32 : iPrev += nCode;
 
271
                }
 
272
                break;
 
273
    }
 
274
  }
 
275
 
 
276
  return ((GByte*)paiOut - pabyOut);
 
277
}
 
278