• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*====================================================================*
2  -  Copyright (C) 2001 Leptonica.  All rights reserved.
3  -  This software is distributed in the hope that it will be
4  -  useful, but with NO WARRANTY OF ANY KIND.
5  -  No author or distributor accepts responsibility to anyone for the
6  -  consequences of using this software, or for whether it serves any
7  -  particular purpose or works at all, unless he or she says so in
8  -  writing.  Everyone is granted permission to copy, modify and
9  -  redistribute this source code, for commercial or non-commercial
10  -  purposes, with the following restrictions: (1) the origin of this
11  -  source code must not be misrepresented; (2) modified versions must
12  -  be plainly marked as such; and (3) this notice may not be removed
13  -  or altered from any source or modified source distribution.
14  *====================================================================*/
15 
16 
17 /*
18  *   zlibmem.c
19  *
20  *      zlib operations in memory, using bbuffer
21  *          l_uint8   *zlibCompress()
22  *          l_uint8   *zlibUncompress()
23  *
24  *
25  *    This provides an example use of the byte buffer utility
26  *    (see bbuffer.c for details of how the bbuffer works internally).
27  *    We use zlib to compress and decompress a byte array from
28  *    one memory buffer to another.  The standard method uses streams,
29  *    but here we use the bbuffer as an expandable queue of pixels
30  *    for both the reading and writing sides of each operation.
31  *
32  *    With memory mapping, one should be able to compress between
33  *    memory buffers by using the file system to buffer everything in
34  *    the background, but the bbuffer implementation is more portable.
35  */
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include "allheaders.h"
40 
41 #ifdef HAVE_CONFIG_H
42 #include "config_auto.h"
43 #endif  /* HAVE_CONFIG_H */
44 
45 /* --------------------------------------------*/
46 #if  HAVE_LIBZ   /* defined in environ.h */
47 /* --------------------------------------------*/
48 
49 #include "zlib.h"
50 
51 static const l_int32  L_BUF_SIZE = 32768;
52 static const l_int32  ZLIB_COMPRESSION_LEVEL = 6;
53 
54 
55 /*!
56  *  zlibCompress()
57  *
58  *      Input:  datain (byte buffer with input data)
59  *              nin    (number of bytes of input data)
60  *              &nout  (<return> number of bytes of output data)
61  *      Return: dataout (compressed data), or null on error
62  *
63  *  Notes:
64  *      (1) We repeatedly read in and fill up an input buffer,
65  *          compress the data, and read it back out.  zlib
66  *          uses two byte buffers internally in the z_stream
67  *          data structure.  We use the bbuffers to feed data
68  *          into the fixed bufferin, and feed it out of bufferout,
69  *          in the same way that a pair of streams would normally
70  *          be used if the data were being read from one file
71  *          and written to another.  This is done iteratively,
72  *          compressing L_BUF_SIZE bytes of input data at a time.
73  */
74 l_uint8 *
zlibCompress(l_uint8 * datain,l_int32 nin,l_int32 * pnout)75 zlibCompress(l_uint8  *datain,
76              l_int32   nin,
77              l_int32  *pnout)
78 {
79 l_uint8  *dataout;
80 l_int32   status, nbytes;
81 l_uint8  *bufferin, *bufferout;
82 BBUFFER  *bbin, *bbout;
83 z_stream  z;
84 
85     PROCNAME("zlibCompress");
86 
87     if (!datain)
88         return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL);
89 
90         /* Set up fixed size buffers used in z_stream */
91     if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
92         return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL);
93     if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
94         return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL);
95 
96         /* Set up bbuffers and load bbin with the data */
97     if ((bbin = bbufferCreate(datain, nin)) == NULL)
98         return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL);
99     if ((bbout = bbufferCreate(NULL, 0)) == NULL)
100         return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL);
101 
102     z.zalloc = (alloc_func)0;
103     z.zfree = (free_func)0;
104     z.opaque = (voidpf)0;
105 
106     z.next_in = bufferin;
107     z.avail_in = 0;
108     z.next_out = bufferout;
109     z.avail_out = L_BUF_SIZE;
110 
111     deflateInit(&z, ZLIB_COMPRESSION_LEVEL);
112 
113     for ( ; ; ) {
114         if (z.avail_in == 0) {
115             z.next_in = bufferin;
116             bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes);
117 /*            fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); */
118             z.avail_in = nbytes;
119         }
120         if (z.avail_in == 0)
121             break;
122         status = deflate(&z, Z_SYNC_FLUSH);
123 /*        fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n",
124                   status, z.avail_out, z.total_out); */
125         nbytes = L_BUF_SIZE - z.avail_out;
126         if (nbytes) {
127             bbufferRead(bbout, bufferout, nbytes);
128 /*            fprintf(stderr, " read %d bytes from bufferout\n", nbytes); */
129         }
130         z.next_out = bufferout;
131         z.avail_out = L_BUF_SIZE;
132     }
133 
134     deflateEnd(&z);
135 
136     bbufferDestroy(&bbin);
137     dataout = bbufferDestroyAndSaveData(&bbout, pnout);
138 
139     FREE(bufferin);
140     FREE(bufferout);
141     return dataout;
142 }
143 
144 
145 /*!
146  *  zlibUncompress()
147  *
148  *      Input:  datain (byte buffer with compressed input data)
149  *              nin    (number of bytes of input data)
150  *              &nout  (<return> number of bytes of output data)
151  *      Return: dataout (uncompressed data), or null on error
152  *
153  *  Notes:
154  *      (1) See zlibCompress().
155  */
156 l_uint8 *
zlibUncompress(l_uint8 * datain,l_int32 nin,l_int32 * pnout)157 zlibUncompress(l_uint8  *datain,
158                l_int32   nin,
159                l_int32  *pnout)
160 {
161 l_uint8  *dataout;
162 l_int32   status, nbytes;
163 l_uint8  *bufferin, *bufferout;
164 BBUFFER  *bbin, *bbout;
165 z_stream  z;
166 
167     PROCNAME("zlibUncompress");
168 
169     if (!datain)
170         return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL);
171 
172     if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
173         return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL);
174     if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
175         return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL);
176 
177     if ((bbin = bbufferCreate(datain, nin)) == NULL)
178         return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL);
179     if ((bbout = bbufferCreate(NULL, 0)) == NULL)
180         return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL);
181 
182     z.zalloc = (alloc_func)0;
183     z.zfree = (free_func)0;
184 
185     z.next_in = bufferin;
186     z.avail_in = 0;
187     z.next_out = bufferout;
188     z.avail_out = L_BUF_SIZE;
189 
190     inflateInit(&z);
191 
192     for ( ; ; ) {
193         if (z.avail_in == 0) {
194             z.next_in = bufferin;
195             bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes);
196 /*            fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); */
197             z.avail_in = nbytes;
198         }
199         if (z.avail_in == 0)
200             break;
201         status = inflate(&z, Z_SYNC_FLUSH);
202 /*        fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n",
203                   status, z.avail_out, z.total_out); */
204         nbytes = L_BUF_SIZE - z.avail_out;
205         if (nbytes) {
206             bbufferRead(bbout, bufferout, nbytes);
207 /*            fprintf(stderr, " read %d bytes from bufferout\n", nbytes); */
208         }
209         z.next_out = bufferout;
210         z.avail_out = L_BUF_SIZE;
211     }
212 
213     inflateEnd(&z);
214 
215     bbufferDestroy(&bbin);
216     dataout = bbufferDestroyAndSaveData(&bbout, pnout);
217 
218     FREE(bufferin);
219     FREE(bufferout);
220     return dataout;
221 }
222 
223 /* --------------------------------------------*/
224 #endif  /* HAVE_LIBZ */
225 /* --------------------------------------------*/
226 
227