#include "mupdf/fitz.h" #include #include static void *fz_z_alloc(void *opaque, unsigned int count, unsigned int size) { fz_context *ctx = (fz_context *)opaque; size_t c = count * size; return fz_malloc_no_throw(ctx, c); } static void fz_z_free(void *opaque, void *addr) { fz_context *ctx = (fz_context *)opaque; fz_free(ctx, addr); } void fz_deflate(fz_context *ctx, unsigned char *dest, size_t *destLen, const unsigned char *source, size_t sourceLen, fz_deflate_level level) { z_stream stream; int err; size_t left; left = *destLen; *destLen = 0; stream.zalloc = fz_z_alloc; stream.zfree = fz_z_free; stream.opaque = ctx; err = deflateInit(&stream, (int)level); if (err != Z_OK) fz_throw(ctx, FZ_ERROR_GENERIC, "zlib compression failed: %d", err); stream.next_out = dest; stream.avail_out = 0; stream.next_in = (z_const Bytef *)source; stream.avail_in = 0; do { if (stream.avail_out == 0) { stream.avail_out = left > UINT_MAX ? UINT_MAX : (uInt)left; left -= stream.avail_out; } if (stream.avail_in == 0) { stream.avail_in = sourceLen > UINT_MAX ? UINT_MAX : (uInt)sourceLen; sourceLen -= stream.avail_in; } err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); } while (err == Z_OK); /* We might have problems if the compressed length > uLong sized. Tough, for now. */ *destLen = stream.total_out; deflateEnd(&stream); if (err != Z_STREAM_END) fz_throw(ctx, FZ_ERROR_GENERIC, "Zlib failure: %d", err); } unsigned char *fz_new_deflated_data(fz_context *ctx, size_t *compressed_length, const unsigned char *source, size_t source_length, fz_deflate_level level) { size_t bound = fz_deflate_bound(ctx, source_length); unsigned char *cdata = fz_malloc(ctx, bound); *compressed_length = 0; fz_try(ctx) fz_deflate(ctx, cdata, &bound, source, source_length, level); fz_catch(ctx) { fz_free(ctx, cdata); fz_rethrow(ctx); } *compressed_length = bound; return cdata; } unsigned char *fz_new_deflated_data_from_buffer(fz_context *ctx, size_t *compressed_length, fz_buffer *buffer, fz_deflate_level level) { unsigned char *data; size_t size = fz_buffer_storage(ctx, buffer, &data); if (size == 0 || data == NULL) { *compressed_length = 0; return NULL; } return fz_new_deflated_data(ctx, compressed_length, data, size, level); } size_t fz_deflate_bound(fz_context *ctx, size_t size) { /* Copied from zlib to account for size_t vs uLong */ return size + (size >> 12) + (size >> 14) + (size >> 25) + 13; }