mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-18 06:06:01 -06:00
226 lines
7.4 KiB
C
226 lines
7.4 KiB
C
/*====================================================================*
|
|
- Copyright (C) 2001 Leptonica. All rights reserved.
|
|
- This software is distributed in the hope that it will be
|
|
- useful, but with NO WARRANTY OF ANY KIND.
|
|
- No author or distributor accepts responsibility to anyone for the
|
|
- consequences of using this software, or for whether it serves any
|
|
- particular purpose or works at all, unless he or she says so in
|
|
- writing. Everyone is granted permission to copy, modify and
|
|
- redistribute this source code, for commercial or non-commercial
|
|
- purposes, with the following restrictions: (1) the origin of this
|
|
- source code must not be misrepresented; (2) modified versions must
|
|
- be plainly marked as such; and (3) this notice may not be removed
|
|
- or altered from any source or modified source distribution.
|
|
*====================================================================*/
|
|
|
|
|
|
/*
|
|
* zlibmem.c
|
|
*
|
|
* zlib operations in memory, using bbuffer
|
|
* l_uint8 *zlibCompress()
|
|
* l_uint8 *zlibUncompress()
|
|
*
|
|
*
|
|
* This provides an example use of the byte buffer utility
|
|
* (see bbuffer.c for details of how the bbuffer works internally).
|
|
* We use zlib to compress and decompress a byte array from
|
|
* one memory buffer to another. The standard method uses streams,
|
|
* but here we use the bbuffer as an expandable queue of pixels
|
|
* for both the reading and writing sides of each operation.
|
|
*
|
|
* With memory mapping, one should be able to compress between
|
|
* memory buffers by using the file system to buffer everything in
|
|
* the background, but the bbuffer implementation is more portable.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "allheaders.h"
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config_auto.h"
|
|
#endif /* HAVE_CONFIG_H */
|
|
|
|
/* --------------------------------------------*/
|
|
#if HAVE_LIBZ /* defined in environ.h */
|
|
/* --------------------------------------------*/
|
|
|
|
#include "zlib.h"
|
|
|
|
static const l_int32 L_BUF_SIZE = 32768;
|
|
static const l_int32 ZLIB_COMPRESSION_LEVEL = 6;
|
|
|
|
|
|
/*!
|
|
* zlibCompress()
|
|
*
|
|
* Input: datain (byte buffer with input data)
|
|
* nin (number of bytes of input data)
|
|
* &nout (<return> number of bytes of output data)
|
|
* Return: dataout (compressed data), or null on error
|
|
*
|
|
* Notes:
|
|
* (1) We repeatedly read in and fill up an input buffer,
|
|
* compress the data, and read it back out. zlib
|
|
* uses two byte buffers internally in the z_stream
|
|
* data structure. We use the bbuffers to feed data
|
|
* into the fixed bufferin, and feed it out of bufferout,
|
|
* in the same way that a pair of streams would normally
|
|
* be used if the data were being read from one file
|
|
* and written to another. This is done iteratively,
|
|
* compressing L_BUF_SIZE bytes of input data at a time.
|
|
*/
|
|
l_uint8 *
|
|
zlibCompress(l_uint8 *datain,
|
|
l_int32 nin,
|
|
l_int32 *pnout)
|
|
{
|
|
l_uint8 *dataout;
|
|
l_int32 status, nbytes;
|
|
l_uint8 *bufferin, *bufferout;
|
|
BBUFFER *bbin, *bbout;
|
|
z_stream z;
|
|
|
|
PROCNAME("zlibCompress");
|
|
|
|
if (!datain)
|
|
return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL);
|
|
|
|
/* Set up fixed size buffers used in z_stream */
|
|
if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL);
|
|
if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL);
|
|
|
|
/* Set up bbuffers and load bbin with the data */
|
|
if ((bbin = bbufferCreate(datain, nin)) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL);
|
|
if ((bbout = bbufferCreate(NULL, 0)) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL);
|
|
|
|
z.zalloc = (alloc_func)0;
|
|
z.zfree = (free_func)0;
|
|
z.opaque = (voidpf)0;
|
|
|
|
z.next_in = bufferin;
|
|
z.avail_in = 0;
|
|
z.next_out = bufferout;
|
|
z.avail_out = L_BUF_SIZE;
|
|
|
|
deflateInit(&z, ZLIB_COMPRESSION_LEVEL);
|
|
|
|
for ( ; ; ) {
|
|
if (z.avail_in == 0) {
|
|
z.next_in = bufferin;
|
|
bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes);
|
|
/* fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); */
|
|
z.avail_in = nbytes;
|
|
}
|
|
if (z.avail_in == 0)
|
|
break;
|
|
status = deflate(&z, Z_SYNC_FLUSH);
|
|
/* fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n",
|
|
status, z.avail_out, z.total_out); */
|
|
nbytes = L_BUF_SIZE - z.avail_out;
|
|
if (nbytes) {
|
|
bbufferRead(bbout, bufferout, nbytes);
|
|
/* fprintf(stderr, " read %d bytes from bufferout\n", nbytes); */
|
|
}
|
|
z.next_out = bufferout;
|
|
z.avail_out = L_BUF_SIZE;
|
|
}
|
|
|
|
deflateEnd(&z);
|
|
|
|
bbufferDestroy(&bbin);
|
|
dataout = bbufferDestroyAndSaveData(&bbout, pnout);
|
|
|
|
FREE(bufferin);
|
|
FREE(bufferout);
|
|
return dataout;
|
|
}
|
|
|
|
|
|
/*!
|
|
* zlibUncompress()
|
|
*
|
|
* Input: datain (byte buffer with compressed input data)
|
|
* nin (number of bytes of input data)
|
|
* &nout (<return> number of bytes of output data)
|
|
* Return: dataout (uncompressed data), or null on error
|
|
*
|
|
* Notes:
|
|
* (1) See zlibCompress().
|
|
*/
|
|
l_uint8 *
|
|
zlibUncompress(l_uint8 *datain,
|
|
l_int32 nin,
|
|
l_int32 *pnout)
|
|
{
|
|
l_uint8 *dataout;
|
|
l_int32 status, nbytes;
|
|
l_uint8 *bufferin, *bufferout;
|
|
BBUFFER *bbin, *bbout;
|
|
z_stream z;
|
|
|
|
PROCNAME("zlibUncompress");
|
|
|
|
if (!datain)
|
|
return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL);
|
|
|
|
if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL);
|
|
if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL);
|
|
|
|
if ((bbin = bbufferCreate(datain, nin)) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL);
|
|
if ((bbout = bbufferCreate(NULL, 0)) == NULL)
|
|
return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL);
|
|
|
|
z.zalloc = (alloc_func)0;
|
|
z.zfree = (free_func)0;
|
|
|
|
z.next_in = bufferin;
|
|
z.avail_in = 0;
|
|
z.next_out = bufferout;
|
|
z.avail_out = L_BUF_SIZE;
|
|
|
|
inflateInit(&z);
|
|
|
|
for ( ; ; ) {
|
|
if (z.avail_in == 0) {
|
|
z.next_in = bufferin;
|
|
bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes);
|
|
/* fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); */
|
|
z.avail_in = nbytes;
|
|
}
|
|
if (z.avail_in == 0)
|
|
break;
|
|
status = inflate(&z, Z_SYNC_FLUSH);
|
|
/* fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n",
|
|
status, z.avail_out, z.total_out); */
|
|
nbytes = L_BUF_SIZE - z.avail_out;
|
|
if (nbytes) {
|
|
bbufferRead(bbout, bufferout, nbytes);
|
|
/* fprintf(stderr, " read %d bytes from bufferout\n", nbytes); */
|
|
}
|
|
z.next_out = bufferout;
|
|
z.avail_out = L_BUF_SIZE;
|
|
}
|
|
|
|
inflateEnd(&z);
|
|
|
|
bbufferDestroy(&bbin);
|
|
dataout = bbufferDestroyAndSaveData(&bbout, pnout);
|
|
|
|
FREE(bufferin);
|
|
FREE(bufferout);
|
|
return dataout;
|
|
}
|
|
|
|
/* --------------------------------------------*/
|
|
#endif /* HAVE_LIBZ */
|
|
/* --------------------------------------------*/
|
|
|