1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include "mupdf/fitz.h"
#include <zlib.h>
#include <limits.h>
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;
}
|