Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 00017 /* 00018 * zlibmem.c 00019 * 00020 * zlib operations in memory, using bbuffer 00021 * l_uint8 *zlibCompress() 00022 * l_uint8 *zlibUncompress() 00023 * 00024 * 00025 * This provides an example use of the byte buffer utility 00026 * (see bbuffer.c for details of how the bbuffer works internally). 00027 * We use zlib to compress and decompress a byte array from 00028 * one memory buffer to another. The standard method uses streams, 00029 * but here we use the bbuffer as an expandable queue of pixels 00030 * for both the reading and writing sides of each operation. 00031 * 00032 * With memory mapping, one should be able to compress between 00033 * memory buffers by using the file system to buffer everything in 00034 * the background, but the bbuffer implementation is more portable. 00035 */ 00036 00037 #include "allheaders.h" 00038 00039 #ifdef HAVE_CONFIG_H 00040 #include "config_auto.h" 00041 #endif /* HAVE_CONFIG_H */ 00042 00043 /* --------------------------------------------*/ 00044 #if HAVE_LIBZ /* defined in environ.h */ 00045 /* --------------------------------------------*/ 00046 00047 #include "zlib.h" 00048 00049 static const l_int32 L_BUF_SIZE = 32768; 00050 static const l_int32 ZLIB_COMPRESSION_LEVEL = 6; 00051 00052 00053 /*! 00054 * zlibCompress() 00055 * 00056 * Input: datain (byte buffer with input data) 00057 * nin (number of bytes of input data) 00058 * &nout (<return> number of bytes of output data) 00059 * Return: dataout (compressed data), or null on error 00060 * 00061 * Notes: 00062 * (1) We repeatedly read in and fill up an input buffer, 00063 * compress the data, and read it back out. zlib 00064 * uses two byte buffers internally in the z_stream 00065 * data structure. We use the bbuffers to feed data 00066 * into the fixed bufferin, and feed it out of bufferout, 00067 * in the same way that a pair of streams would normally 00068 * be used if the data were being read from one file 00069 * and written to another. This is done iteratively, 00070 * compressing L_BUF_SIZE bytes of input data at a time. 00071 */ 00072 l_uint8 * 00073 zlibCompress(l_uint8 *datain, 00074 size_t nin, 00075 size_t *pnout) 00076 { 00077 l_uint8 *dataout; 00078 l_int32 status; 00079 size_t nbytes; 00080 l_uint8 *bufferin, *bufferout; 00081 BBUFFER *bbin, *bbout; 00082 z_stream z; 00083 00084 PROCNAME("zlibCompress"); 00085 00086 if (!datain) 00087 return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL); 00088 00089 /* Set up fixed size buffers used in z_stream */ 00090 if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) 00091 return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL); 00092 if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) 00093 return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL); 00094 00095 /* Set up bbuffers and load bbin with the data */ 00096 if ((bbin = bbufferCreate(datain, nin)) == NULL) 00097 return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL); 00098 if ((bbout = bbufferCreate(NULL, 0)) == NULL) 00099 return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL); 00100 00101 z.zalloc = (alloc_func)0; 00102 z.zfree = (free_func)0; 00103 z.opaque = (voidpf)0; 00104 00105 z.next_in = bufferin; 00106 z.avail_in = 0; 00107 z.next_out = bufferout; 00108 z.avail_out = L_BUF_SIZE; 00109 00110 deflateInit(&z, ZLIB_COMPRESSION_LEVEL); 00111 00112 for ( ; ; ) { 00113 if (z.avail_in == 0) { 00114 z.next_in = bufferin; 00115 bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes); 00116 /* fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); */ 00117 z.avail_in = nbytes; 00118 } 00119 if (z.avail_in == 0) 00120 break; 00121 status = deflate(&z, Z_SYNC_FLUSH); 00122 /* fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n", 00123 status, z.avail_out, z.total_out); */ 00124 nbytes = L_BUF_SIZE - z.avail_out; 00125 if (nbytes) { 00126 bbufferRead(bbout, bufferout, nbytes); 00127 /* fprintf(stderr, " read %d bytes from bufferout\n", nbytes); */ 00128 } 00129 z.next_out = bufferout; 00130 z.avail_out = L_BUF_SIZE; 00131 } 00132 00133 deflateEnd(&z); 00134 00135 bbufferDestroy(&bbin); 00136 dataout = bbufferDestroyAndSaveData(&bbout, pnout); 00137 00138 FREE(bufferin); 00139 FREE(bufferout); 00140 return dataout; 00141 } 00142 00143 00144 /*! 00145 * zlibUncompress() 00146 * 00147 * Input: datain (byte buffer with compressed input data) 00148 * nin (number of bytes of input data) 00149 * &nout (<return> number of bytes of output data) 00150 * Return: dataout (uncompressed data), or null on error 00151 * 00152 * Notes: 00153 * (1) See zlibCompress(). 00154 */ 00155 l_uint8 * 00156 zlibUncompress(l_uint8 *datain, 00157 size_t nin, 00158 size_t *pnout) 00159 { 00160 l_uint8 *dataout; 00161 l_uint8 *bufferin, *bufferout; 00162 l_int32 status; 00163 size_t nbytes; 00164 BBUFFER *bbin, *bbout; 00165 z_stream z; 00166 00167 PROCNAME("zlibUncompress"); 00168 00169 if (!datain) 00170 return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL); 00171 00172 if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) 00173 return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL); 00174 if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) 00175 return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL); 00176 00177 if ((bbin = bbufferCreate(datain, nin)) == NULL) 00178 return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL); 00179 if ((bbout = bbufferCreate(NULL, 0)) == NULL) 00180 return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL); 00181 00182 z.zalloc = (alloc_func)0; 00183 z.zfree = (free_func)0; 00184 00185 z.next_in = bufferin; 00186 z.avail_in = 0; 00187 z.next_out = bufferout; 00188 z.avail_out = L_BUF_SIZE; 00189 00190 inflateInit(&z); 00191 00192 for ( ; ; ) { 00193 if (z.avail_in == 0) { 00194 z.next_in = bufferin; 00195 bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes); 00196 /* fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); */ 00197 z.avail_in = nbytes; 00198 } 00199 if (z.avail_in == 0) 00200 break; 00201 status = inflate(&z, Z_SYNC_FLUSH); 00202 /* fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n", 00203 status, z.avail_out, z.total_out); */ 00204 nbytes = L_BUF_SIZE - z.avail_out; 00205 if (nbytes) { 00206 bbufferRead(bbout, bufferout, nbytes); 00207 /* fprintf(stderr, " read %d bytes from bufferout\n", nbytes); */ 00208 } 00209 z.next_out = bufferout; 00210 z.avail_out = L_BUF_SIZE; 00211 } 00212 00213 inflateEnd(&z); 00214 00215 bbufferDestroy(&bbin); 00216 dataout = bbufferDestroyAndSaveData(&bbout, pnout); 00217 00218 FREE(bufferin); 00219 FREE(bufferout); 00220 return dataout; 00221 } 00222 00223 /* --------------------------------------------*/ 00224 #endif /* HAVE_LIBZ */ 00225 /* --------------------------------------------*/ 00226