comparison mupdf-source/thirdparty/leptonica/src/zlibmem.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
27
28 /*!
29 * \file zlibmem.c
30 * <pre>
31 *
32 * zlib operations in memory, using bbuffer
33 * l_uint8 *zlibCompress()
34 * l_uint8 *zlibUncompress()
35 *
36 *
37 * This provides an example use of the byte buffer utility
38 * (see bbuffer.c for details of how the bbuffer works internally).
39 * We use zlib to compress and decompress a byte array from
40 * one memory buffer to another. The standard method uses streams,
41 * but here we use the bbuffer as an expandable queue of pixels
42 * for both the reading and writing sides of each operation.
43 *
44 * With memory mapping, one should be able to compress between
45 * memory buffers by using the file system to buffer everything in
46 * the background, but the bbuffer implementation is more portable.
47 * </pre>
48 */
49
50 #ifdef HAVE_CONFIG_H
51 #include <config_auto.h>
52 #endif /* HAVE_CONFIG_H */
53
54 #include "allheaders.h"
55
56 /* --------------------------------------------*/
57 #if HAVE_LIBZ /* defined in environ.h */
58 /* --------------------------------------------*/
59
60 #include "zlib.h"
61
62 static const l_int32 L_BUF_SIZE = 32768;
63 static const l_int32 ZLIB_COMPRESSION_LEVEL = 6;
64
65 #ifndef NO_CONSOLE_IO
66 #define DEBUG 0
67 #endif /* ~NO_CONSOLE_IO */
68
69
70 /*!
71 * \brief zlibCompress()
72 *
73 * \param[in] datain byte buffer with input data
74 * \param[in] nin number of bytes of input data
75 * \param[out] pnout number of bytes of output data
76 * \return dataout compressed data, or NULL on error
77 *
78 * <pre>
79 * Notes:
80 * (1) We repeatedly read in and fill up an input buffer,
81 * compress the data, and read it back out. zlib
82 * uses two byte buffers internally in the z_stream
83 * data structure. We use the bbuffers to feed data
84 * into the fixed bufferin, and feed it out of bufferout,
85 * in the same way that a pair of streams would normally
86 * be used if the data were being read from one file
87 * and written to another. This is done iteratively,
88 * compressing L_BUF_SIZE bytes of input data at a time.
89 * </pre>
90 */
91 l_uint8 *
92 zlibCompress(const l_uint8 *datain,
93 size_t nin,
94 size_t *pnout)
95 {
96 l_uint8 *dataout;
97 l_int32 status, success;
98 l_int32 flush;
99 size_t nbytes;
100 l_uint8 *bufferin, *bufferout;
101 L_BBUFFER *bbin, *bbout;
102 z_stream z;
103
104 if (!datain)
105 return (l_uint8 *)ERROR_PTR("datain not defined", __func__, NULL);
106
107 /* Set up fixed size buffers used in z_stream */
108 bufferin = (l_uint8 *)LEPT_CALLOC(L_BUF_SIZE, sizeof(l_uint8));
109 bufferout = (l_uint8 *)LEPT_CALLOC(L_BUF_SIZE, sizeof(l_uint8));
110
111 /* Set up bbuffers and load bbin with the data */
112 bbin = bbufferCreate(datain, nin);
113 bbout = bbufferCreate(NULL, 0);
114
115 success = TRUE;
116 if (!bufferin || !bufferout || !bbin || !bbout) {
117 L_ERROR("calloc fail for buffer\n", __func__);
118 success = FALSE;
119 goto cleanup_arrays;
120 }
121
122 z.zalloc = (alloc_func)0;
123 z.zfree = (free_func)0;
124 z.opaque = (voidpf)0;
125 z.next_in = bufferin;
126 z.avail_in = 0;
127 z.next_out = bufferout;
128 z.avail_out = L_BUF_SIZE;
129
130 status = deflateInit(&z, ZLIB_COMPRESSION_LEVEL);
131 if (status != Z_OK) {
132 L_ERROR("deflateInit failed\n", __func__);
133 success = FALSE;
134 goto cleanup_arrays;
135 }
136
137 do {
138 if (z.avail_in == 0) {
139 z.next_in = bufferin;
140 bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes);
141 #if DEBUG
142 lept_stderr(" wrote %zu bytes to bufferin\n", nbytes);
143 #endif /* DEBUG */
144 z.avail_in = nbytes;
145 }
146 flush = (bbin->n) ? Z_SYNC_FLUSH : Z_FINISH;
147 status = deflate(&z, flush);
148 #if DEBUG
149 lept_stderr(" status is %d, bytesleft = %u, totalout = %zu\n",
150 status, z.avail_out, z.total_out);
151 #endif /* DEBUG */
152 nbytes = L_BUF_SIZE - z.avail_out;
153 if (nbytes) {
154 bbufferRead(bbout, bufferout, nbytes);
155 #if DEBUG
156 lept_stderr(" read %zu bytes from bufferout\n", nbytes);
157 #endif /* DEBUG */
158 }
159 z.next_out = bufferout;
160 z.avail_out = L_BUF_SIZE;
161 } while (flush != Z_FINISH);
162
163 deflateEnd(&z);
164
165 cleanup_arrays:
166 if (success) {
167 dataout = bbufferDestroyAndSaveData(&bbout, pnout);
168 } else {
169 dataout = NULL;
170 bbufferDestroy(&bbout);
171 }
172 bbufferDestroy(&bbin);
173 LEPT_FREE(bufferin);
174 LEPT_FREE(bufferout);
175 return dataout;
176 }
177
178
179 /*!
180 * \brief zlibUncompress()
181 *
182 * \param[in] datain byte buffer with compressed input data
183 * \param[in] nin number of bytes of input data
184 * \param[out] pnout number of bytes of output data
185 * \return dataout uncompressed data, or NULL on error
186 *
187 * <pre>
188 * Notes:
189 * (1) See zlibCompress().
190 * </pre>
191 */
192 l_uint8 *
193 zlibUncompress(const l_uint8 *datain,
194 size_t nin,
195 size_t *pnout)
196 {
197 l_uint8 *dataout;
198 l_uint8 *bufferin, *bufferout;
199 l_int32 status, success;
200 size_t nbytes;
201 L_BBUFFER *bbin, *bbout;
202 z_stream z;
203
204 if (!datain)
205 return (l_uint8 *)ERROR_PTR("datain not defined", __func__, NULL);
206
207 /* Set up fixed size buffers used in z_stream */
208 bufferin = (l_uint8 *)LEPT_CALLOC(L_BUF_SIZE, sizeof(l_uint8));
209 bufferout = (l_uint8 *)LEPT_CALLOC(L_BUF_SIZE, sizeof(l_uint8));
210
211 /* Set up bbuffers and load bbin with the data */
212 bbin = bbufferCreate(datain, nin);
213 bbout = bbufferCreate(NULL, 0);
214
215 success = TRUE;
216 if (!bufferin || !bufferout || !bbin || !bbout) {
217 L_ERROR("calloc fail for buffer\n", __func__);
218 success = FALSE;
219 goto cleanup_arrays;
220 }
221
222 z.zalloc = (alloc_func)0;
223 z.zfree = (free_func)0;
224 z.next_in = bufferin;
225 z.avail_in = 0;
226 z.next_out = bufferout;
227 z.avail_out = L_BUF_SIZE;
228
229 status = inflateInit(&z);
230 if (status != Z_OK) {
231 L_ERROR("inflateInit fail for buffer\n", __func__);
232 success = FALSE;
233 goto cleanup_arrays;
234 }
235
236 for ( ; ; ) {
237 if (z.avail_in == 0) {
238 z.next_in = bufferin;
239 bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes);
240 #if DEBUG
241 lept_stderr(" wrote %d bytes to bufferin\n", nbytes);
242 #endif /* DEBUG */
243 z.avail_in = nbytes;
244 }
245 if (z.avail_in == 0)
246 break;
247 status = inflate(&z, Z_SYNC_FLUSH);
248 #if DEBUG
249 lept_stderr(" status is %d, bytesleft = %d, totalout = %d\n",
250 status, z.avail_out, z.total_out);
251 #endif /* DEBUG */
252 nbytes = L_BUF_SIZE - z.avail_out;
253 if (nbytes) {
254 bbufferRead(bbout, bufferout, nbytes);
255 #if DEBUG
256 lept_stderr(" read %d bytes from bufferout\n", nbytes);
257 #endif /* DEBUG */
258 }
259 z.next_out = bufferout;
260 z.avail_out = L_BUF_SIZE;
261 }
262
263 inflateEnd(&z);
264
265 cleanup_arrays:
266 if (success) {
267 dataout = bbufferDestroyAndSaveData(&bbout, pnout);
268 } else {
269 dataout = NULL;
270 bbufferDestroy(&bbout);
271 }
272 bbufferDestroy(&bbin);
273 LEPT_FREE(bufferin);
274 LEPT_FREE(bufferout);
275 return dataout;
276 }
277
278 /* --------------------------------------------*/
279 #endif /* HAVE_LIBZ */
280 /* --------------------------------------------*/