GRASS GIS 7 Programmer's Manual  7.4.3(2018)-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 
67 int
68 G_rle_compress(unsigned char *src, int src_sz, unsigned char *dst,
69  int dst_sz)
70 {
71  int i, nbytes;
72  unsigned char prev_b;
73  int cnt;
74 
75  /* Catch errors early */
76  if (src == NULL || dst == NULL)
77  return -1;
78 
79  /* Don't do anything if src is empty or smaller than 4 bytes */
80  if (src_sz <= 3)
81  return 0;
82 
83  /* modified RLE:
84  * unit is 1 byte, only sequences longer than 1 are encoded
85  * single occurrences don't have a following count
86  * multiple occurrences are twice in dst, followed by the count
87  * example:
88  * ABBCCC
89  * is encoded as
90  * ABB2CC3
91  */
92 
93  prev_b = src[0];
94  cnt = 1;
95  nbytes = 0;
96  for (i = 1; i < src_sz; i++) {
97  if (prev_b != src[i] || cnt == 255) {
98  /* write to dst */
99  if (cnt == 1) {
100  if (nbytes >= dst_sz)
101  return -2;
102  dst[nbytes++] = prev_b;
103  }
104  else {
105  /* cnt > 1 */
106  if (nbytes >= dst_sz - 2)
107  return -2;
108  dst[nbytes++] = prev_b;
109  dst[nbytes++] = prev_b;
110  dst[nbytes++] = (unsigned char) cnt;
111  }
112  cnt = 0;
113  }
114  prev_b = src[i];
115  cnt++;
116  }
117  /* write out the last sequence */
118  if (cnt == 1) {
119  if (nbytes >= dst_sz)
120  return -2;
121  dst[nbytes++] = prev_b;
122  }
123  else {
124  if (nbytes >= dst_sz - 2)
125  return -2;
126  dst[nbytes++] = prev_b;
127  dst[nbytes++] = prev_b;
128  dst[nbytes++] = (unsigned char) cnt;
129  }
130 
131  return nbytes;
132 }
133 
134 int
135 G_rle_expand(unsigned char *src, int src_sz, unsigned char *dst,
136  int dst_sz)
137 {
138  int i, j, nbytes, cnt;
139  unsigned char prev_b;
140 
141  /* Catch errors early */
142  if (src == NULL || dst == NULL)
143  return -1;
144 
145  /* Don't do anything if src is empty */
146  if (src_sz <= 0)
147  return 0;
148 
149  /* RLE expand */
150  prev_b = src[0];
151  cnt = 1;
152  nbytes = 0;
153  i = 1;
154  while (i < src_sz) {
155  /* single occurrences don't have a following count
156  * multiple occurrences are twice in src, followed by the count */
157  if (cnt == 2) {
158  if (i >= src_sz)
159  return -1;
160  cnt = src[i];
161  if (nbytes + cnt > dst_sz)
162  return -1;
163  for (j = 0; j < cnt; j++) {
164  dst[nbytes++] = prev_b;
165  }
166  cnt = 0;
167  i++;
168  if (i >= src_sz)
169  return nbytes;
170  }
171  if (cnt == 1) {
172  if (prev_b != src[i]) {
173  if (nbytes + cnt > dst_sz)
174  return -1;
175  dst[nbytes++] = prev_b;
176  cnt = 0;
177  }
178  }
179  prev_b = src[i];
180  cnt++;
181  i++;
182  }
183  if (nbytes >= dst_sz)
184  return -1;
185  if (cnt == 1)
186  dst[nbytes++] = prev_b;
187 
188  return nbytes;
189 }
190 
191 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
int G_rle_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprrle.c:68
char * dst
Definition: lz4.h:354
#define NULL
Definition: ccmath.h:32
int G_rle_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprrle.c:135