GRASS 8 Programmer's Manual 8.6.0dev(2026)-55de52a352
Loading...
Searching...
No Matches
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 * SPDX-FileCopyrightText: 2015 GRASS Development Team
15 * SPDX-License-Identifier: GPL-2.0-or-later
16 *
17 *****************************************************************************/
18
19/********************************************************************
20 * int *
21 * G_rle_compress (src, srz_sz, dst, dst_sz) *
22 * int src_sz, dst_sz; *
23 * unsigned char *src, *dst; *
24 * ---------------------------------------------------------------- *
25 * This function compresses data with RLE. *
26 * It uses an all or nothing call. *
27 * If you need a continuous compression scheme, you'll have to code *
28 * your own. *
29 * *
30 * The function either returns the number of bytes of compressed *
31 * data in dst, or an error code. *
32 * *
33 * Errors include: *
34 * -1 -- Compression failed. *
35 * -2 -- dst is too small. *
36 * *
37 * ================================================================ *
38 * int *
39 * G_rle_expand (src, src_sz, dst, dst_sz) *
40 * int src_sz, dst_sz; *
41 * unsigned char *src, *dst; *
42 * ---------------------------------------------------------------- *
43 * This function decompresses data compressed with RLE. *
44 * It is equivalent to a single pass call to an external expansion *
45 * function. *
46 * If you need a continuous expansion scheme, you'll have to code *
47 * your own. *
48 * *
49 * The function returns the number of bytes expanded into 'dst' or *
50 * and error code. *
51 * *
52 * Errors include: *
53 * -1 -- Expansion failed. *
54 * *
55 ********************************************************************
56 */
57
58#include <grass/config.h>
59
60#include <grass/gis.h>
61#include <grass/glocale.h>
62
63/* no fast mode if destination is large enough to hold
64 * worst case compression */
66{
67 return ((src_sz >> 1) * 3 + (src_sz & 1));
68}
69
70int G_rle_compress(unsigned char *src, int src_sz, unsigned char *dst,
71 int dst_sz)
72{
73 int i, nbytes;
74 unsigned char prev_b;
75 int cnt;
76
77 /* Catch errors early */
78 if (src == NULL || dst == NULL)
79 return -1;
80
81 /* Don't do anything if src is empty or smaller than 4 bytes */
82 if (src_sz <= 3)
83 return 0;
84
85 /* modified RLE:
86 * unit is 1 byte, only sequences longer than 1 are encoded
87 * single occurrences don't have a following count
88 * multiple occurrences are twice in dst, followed by the count
89 * example:
90 * ABBCCC
91 * is encoded as
92 * ABB2CC3
93 */
94
95 prev_b = src[0];
96 cnt = 1;
97 nbytes = 0;
98 for (i = 1; i < src_sz; i++) {
99 if (prev_b != src[i] || cnt == 255) {
100 /* write to dst */
101 if (cnt == 1) {
102 if (nbytes >= dst_sz)
103 return -2;
104 dst[nbytes++] = prev_b;
105 }
106 else {
107 /* cnt > 1 */
108 if (nbytes >= dst_sz - 2)
109 return -2;
110 dst[nbytes++] = prev_b;
111 dst[nbytes++] = prev_b;
112 dst[nbytes++] = (unsigned char)cnt;
113 }
114 cnt = 0;
115 }
116 prev_b = src[i];
117 cnt++;
118 }
119 /* write out the last sequence */
120 if (cnt == 1) {
121 if (nbytes >= dst_sz)
122 return -2;
123 dst[nbytes++] = prev_b;
124 }
125 else {
126 if (nbytes >= dst_sz - 2)
127 return -2;
128 dst[nbytes++] = prev_b;
129 dst[nbytes++] = prev_b;
130 dst[nbytes++] = (unsigned char)cnt;
131 }
132
133 return nbytes;
134}
135
136int G_rle_expand(unsigned char *src, int src_sz, unsigned char *dst, 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: */
#define NULL
Definition ccmath.h:32
int G_rle_compress_bound(int src_sz)
Definition cmprrle.c:65
int G_rle_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprrle.c:70
int G_rle_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprrle.c:136