GRASS GIS 7 Programmer's Manual
7.8.2(2019)-exported
cmprrle.c
Go to the documentation of this file.
1
/*
2
****************************************************************************
3
* -- GRASS Development Team --
4
*
5
* MODULE: GRASS gis library
6
* FILENAME: cmprrle.c
7
* AUTHOR(S): Markus Metz
8
* PURPOSE: To provide generic RLE for compressing and
9
* decompressing data. Its primary use is in
10
* the storage and reading of GRASS rasters.
11
*
12
* ALGORITHM: Run Length Encoding
13
* DATE CREATED: Dec 18 2015
14
* COPYRIGHT: (C) 2015 by the GRASS Development Team
15
*
16
* This program is free software under the GNU General Public
17
* License (version 2 or greater). Read the file COPYING that
18
* comes with GRASS for details.
19
*
20
*****************************************************************************/
21
22
/********************************************************************
23
* int *
24
* G_rle_compress (src, srz_sz, dst, dst_sz) *
25
* int src_sz, dst_sz; *
26
* unsigned char *src, *dst; *
27
* ---------------------------------------------------------------- *
28
* This function compresses data with RLE. *
29
* It uses an all or nothing call. *
30
* If you need a continuous compression scheme, you'll have to code *
31
* your own. *
32
* *
33
* The function either returns the number of bytes of compressed *
34
* data in dst, or an error code. *
35
* *
36
* Errors include: *
37
* -1 -- Compression failed. *
38
* -2 -- dst is too small. *
39
* *
40
* ================================================================ *
41
* int *
42
* G_rle_expand (src, src_sz, dst, dst_sz) *
43
* int src_sz, dst_sz; *
44
* unsigned char *src, *dst; *
45
* ---------------------------------------------------------------- *
46
* This function decompresses data compressed with RLE. *
47
* It is equivalent to a single pass call to an external expansion *
48
* function. *
49
* If you need a continuous expansion scheme, you'll have to code *
50
* your own. *
51
* *
52
* The function returns the number of bytes expanded into 'dst' or *
53
* and error code. *
54
* *
55
* Errors include: *
56
* -1 -- Expansion failed. *
57
* *
58
********************************************************************
59
*/
60
61
#include <grass/config.h>
62
63
#include <grass/gis.h>
64
#include <grass/glocale.h>
65
66
/* no fast mode if destination is large enough to hold
67
* worst case compression */
68
int
G_rle_compress_bound
(
int
src_sz)
69
{
70
return
((src_sz >> 1) * 3 + (src_sz & 1));
71
}
72
73
int
74
G_rle_compress
(
unsigned
char
*src,
int
src_sz,
unsigned
char
*
dst
,
75
int
dst_sz)
76
{
77
int
i, nbytes;
78
unsigned
char
prev_b;
79
int
cnt;
80
81
/* Catch errors early */
82
if
(src ==
NULL
||
dst
==
NULL
)
83
return
-1;
84
85
/* Don't do anything if src is empty or smaller than 4 bytes */
86
if
(src_sz <= 3)
87
return
0;
88
89
/* modified RLE:
90
* unit is 1 byte, only sequences longer than 1 are encoded
91
* single occurrences don't have a following count
92
* multiple occurrences are twice in dst, followed by the count
93
* example:
94
* ABBCCC
95
* is encoded as
96
* ABB2CC3
97
*/
98
99
prev_b = src[0];
100
cnt = 1;
101
nbytes = 0;
102
for
(i = 1; i < src_sz; i++) {
103
if
(prev_b != src[i] || cnt == 255) {
104
/* write to dst */
105
if
(cnt == 1) {
106
if
(nbytes >= dst_sz)
107
return
-2;
108
dst
[nbytes++] = prev_b;
109
}
110
else
{
111
/* cnt > 1 */
112
if
(nbytes >= dst_sz - 2)
113
return
-2;
114
dst
[nbytes++] = prev_b;
115
dst
[nbytes++] = prev_b;
116
dst
[nbytes++] = (
unsigned
char) cnt;
117
}
118
cnt = 0;
119
}
120
prev_b = src[i];
121
cnt++;
122
}
123
/* write out the last sequence */
124
if
(cnt == 1) {
125
if
(nbytes >= dst_sz)
126
return
-2;
127
dst
[nbytes++] = prev_b;
128
}
129
else
{
130
if
(nbytes >= dst_sz - 2)
131
return
-2;
132
dst
[nbytes++] = prev_b;
133
dst
[nbytes++] = prev_b;
134
dst
[nbytes++] = (
unsigned
char) cnt;
135
}
136
137
return
nbytes;
138
}
139
140
int
141
G_rle_expand
(
unsigned
char
*src,
int
src_sz,
unsigned
char
*
dst
,
142
int
dst_sz)
143
{
144
int
i, j, nbytes, cnt;
145
unsigned
char
prev_b;
146
147
/* Catch errors early */
148
if
(src ==
NULL
||
dst
==
NULL
)
149
return
-1;
150
151
/* Don't do anything if src is empty */
152
if
(src_sz <= 0)
153
return
0;
154
155
/* RLE expand */
156
prev_b = src[0];
157
cnt = 1;
158
nbytes = 0;
159
i = 1;
160
while
(i < src_sz) {
161
/* single occurrences don't have a following count
162
* multiple occurrences are twice in src, followed by the count */
163
if
(cnt == 2) {
164
if
(i >= src_sz)
165
return
-1;
166
cnt = src[i];
167
if
(nbytes + cnt > dst_sz)
168
return
-1;
169
for
(j = 0; j < cnt; j++) {
170
dst
[nbytes++] = prev_b;
171
}
172
cnt = 0;
173
i++;
174
if
(i >= src_sz)
175
return
nbytes;
176
}
177
if
(cnt == 1) {
178
if
(prev_b != src[i]) {
179
if
(nbytes + cnt > dst_sz)
180
return
-1;
181
dst
[nbytes++] = prev_b;
182
cnt = 0;
183
}
184
}
185
prev_b = src[i];
186
cnt++;
187
i++;
188
}
189
if
(nbytes >= dst_sz)
190
return
-1;
191
if
(cnt == 1)
192
dst
[nbytes++] = prev_b;
193
194
return
nbytes;
195
}
196
197
/* vim: set softtabstop=4 shiftwidth=4 expandtab: */
G_rle_compress
int G_rle_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition:
cmprrle.c:73
G_rle_expand
int G_rle_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition:
cmprrle.c:140
NULL
#define NULL
Definition:
ccmath.h:32
G_rle_compress_bound
int G_rle_compress_bound(int src_sz)
Definition:
cmprrle.c:67
dst
char * dst
Definition:
lz4.h:599
gis
cmprrle.c
Generated on Tue Dec 24 2019 19:34:28 for GRASS GIS 7 Programmer's Manual by
1.8.16