GRASS 8 Programmer's Manual 8.6.0dev(2026)-55de52a352
Loading...
Searching...
No Matches
cmprzlib.c
Go to the documentation of this file.
1/*****************************************************************************
2 * -- GRASS Development Team --
3 *
4 * MODULE: GRASS gis library
5 * FILENAME: cmprzlib.c
6 * AUTHOR(S): Eric G. Miller <egm2@jps.net>
7 * Markus Metz
8 * PURPOSE: To provide an interface to libz for compressing and
9 * decompressing data using DEFLATE. It's primary use is in
10 * the storage and reading of GRASS floating point rasters.
11 * It replaces the patented LZW compression interface.
12 *
13 * ALGORITHM: http://www.gzip.org/zlib/feldspar.html
14 * DATE CREATED: Dec 17 2015
15 * SPDX-FileCopyrightText: 2015 GRASS Development Team
16 * SPDX-License-Identifier: GPL-2.0-or-later
17 *
18 *****************************************************************************/
19
20/********************************************************************
21 * int *
22 * G_zlib_compress (src, srz_sz, dst, dst_sz) *
23 * int src_sz, dst_sz; *
24 * unsigned char *src, *dst; *
25 * ---------------------------------------------------------------- *
26 * This function is a wrapper around the zlib deflate() function. *
27 * It uses an all or nothing call to deflate(). If you need a *
28 * continuous compression scheme, you'll have to code your own. *
29 * In order to do a single pass compression, the input src must be *
30 * copied to a buffer 1% + 12 bytes larger than the data. This may *
31 * cause performance degradation. *
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_zlib_expand (src, src_sz, dst, dst_sz) *
43 * int src_sz, dst_sz; *
44 * unsigned char *src, *dst; *
45 * ---------------------------------------------------------------- *
46 * This function is a wrapper around the zlib inflate() function. *
47 * It uses a single pass call to inflate(). If you need a contin- *
48 * uous expansion scheme, you'll have to code your own. *
49 * *
50 * The function returns the number of bytes expanded into 'dst' or *
51 * and error code. *
52 * *
53 * Errors include: *
54 * -1 -- Expansion failed. *
55 * *
56 ********************************************************************
57 */
58
59#include <grass/config.h>
60
61#ifndef HAVE_ZLIB_H
62
63#error "GRASS requires libz to compile"
64
65#else
66
67#include <zlib.h>
68#include <grass/gis.h>
69#include <grass/glocale.h>
70
71#include "G.h"
72
74{
75 /* from zlib.h:
76 * "when using compress or compress2,
77 * destLen must be at least the value returned by
78 * compressBound(sourceLen)"
79 * no explanation for the "must be"
80 */
81 return compressBound(src_sz);
82}
83
84int G_zlib_compress(unsigned char *src, int src_sz, unsigned char *dst,
85 int dst_sz)
86{
87 uLong err, nbytes, buf_sz;
88 unsigned char *buf;
89
90 /* Catch errors early */
91 if (src == NULL || dst == NULL) {
92 if (src == NULL)
93 G_warning(_("No source buffer"));
94
95 if (dst == NULL)
96 G_warning(_("No destination buffer"));
97 return -1;
98 }
99
100 /* Don't do anything if either of these are true */
101 if (src_sz <= 0 || dst_sz <= 0) {
102 if (src_sz <= 0)
103 G_warning(_("Invalid source buffer size %d"), src_sz);
104 if (dst_sz <= 0)
105 G_warning(_("Invalid destination buffer size %d"), dst_sz);
106 return 0;
107 }
108
109 /* Output buffer has to be 1% + 12 bytes bigger for single pass deflate */
110 /* buf_sz = (int)((double)dst_sz * 1.01 + (double)12); */
111
112 /* Output buffer should be large enough for single pass compression */
113 buf = dst;
115 if (dst_sz < 0 || buf_sz > (unsigned int)dst_sz) {
116 G_warning(
117 "G_zlib_compress(): programmer error, destination is too small");
118 if (NULL ==
119 (buf = (unsigned char *)G_calloc(buf_sz, sizeof(unsigned char))))
120 return -1;
121 }
122 else
123 buf_sz = dst_sz;
124
125 /* Valid zlib compression levels -1 - 9 */
126 /* zlib default: Z_DEFAULT_COMPRESSION = -1, equivalent to 6
127 * as used here, 1 gives the best compromise between speed and compression
128 */
129
130 /* Do single pass compression */
131 nbytes = buf_sz;
132 err = compress2((Bytef *)buf, &nbytes, /* destination */
133 (const Bytef *)src, src_sz, /* source */
134 G__.compression_level); /* level */
135
136 if (err != Z_OK) {
137 G_warning(_("ZLIB compression error %d: %s"), (int)err, zError(err));
138 if (buf != dst)
139 G_free(buf);
140 return -1;
141 }
142
143 /* updated buf_sz is bytes of compressed data */
144 if (src_sz < 0 || nbytes >= (unsigned int)src_sz) {
145 /* compression not possible */
146 if (buf != dst)
147 G_free(buf);
148 return -2;
149 }
150
151 if (buf != dst) {
152 /* Copy the data from buf to dst */
153 for (err = 0; err < nbytes; err++)
154 dst[err] = buf[err];
155
156 G_free(buf);
157 }
158
159 return nbytes;
160} /* G_zlib_compress() */
161
162int G_zlib_expand(unsigned char *src, int src_sz, unsigned char *dst,
163 int dst_sz)
164{
165 int err;
166 uLong ss, nbytes;
167
168 /* Catch error condition */
169 if (src == NULL || dst == NULL) {
170 if (src == NULL)
171 G_warning(_("No source buffer"));
172
173 if (dst == NULL)
174 G_warning(_("No destination buffer"));
175 return -2;
176 }
177
178 /* Don't do anything if either of these are true */
179 if (src_sz <= 0 || dst_sz <= 0) {
180 if (src_sz <= 0)
181 G_warning(_("Invalid source buffer size %d"), src_sz);
182 if (dst_sz <= 0)
183 G_warning(_("Invalid destination buffer size %d"), dst_sz);
184 return 0;
185 }
186
187 ss = src_sz;
188
189 /* Do single pass decompression */
190 nbytes = dst_sz;
191 err = uncompress((Bytef *)dst, &nbytes, /* destination */
192 (const Bytef *)src, ss); /* source */
193
194 /* If not Z_OK return error -1 */
195 if (err != Z_OK) {
196 G_warning(_("ZLIB decompression error %d: %s"), err, zError(err));
197 return -1;
198 }
199
200 /* Number of bytes inflated to output stream is
201 * updated buffer size
202 */
203
204 if (dst_sz < 0 || nbytes != (unsigned int)dst_sz) {
205 /* TODO: it is not an error if destination is larger than needed */
206 G_warning(_("Got uncompressed size %d, expected %d"), (int)nbytes,
207 dst_sz);
208 return -1;
209 }
210
211 return nbytes;
212} /* G_zlib_expand() */
213
214#endif /* HAVE_ZLIB_H */
215
216/* vim: set softtabstop=4 shiftwidth=4 expandtab: */
#define NULL
Definition ccmath.h:32
int G_zlib_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprzlib.c:162
int G_zlib_compress_bound(int src_sz)
Definition cmprzlib.c:73
int G_zlib_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprzlib.c:84
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_calloc(m, n)
Definition defs/gis.h:137
void G_warning(const char *,...) __attribute__((format(printf
#define _(str)
Definition glocale.h:10
Definition G.h:11
int compression_level
Definition G.h:15
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)