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