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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
// ==========================================================
// ZLib library interface
//
// Design and implementation by
// - Floris van den Berg (flvdberg@wxs.nl)
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// ==========================================================
#include "../stdafx.h"
#include "zlib.h"
#include "zutil.h" /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */
/**
Compresses a source buffer into a target buffer, using the ZLib library.
Upon entry, target_size is the total size of the destination buffer,
which must be at least 0.1% larger than source_size plus 12 bytes.
@param target Destination buffer
@param target_size Size of the destination buffer, in bytes
@param source Source buffer
@param source_size Size of the source buffer, in bytes
@return Returns the actual size of the compressed buffer, returns 0 if an error occured
@see FreeImage_ZLibUncompress
*/
DWORD DLL_CALLCONV
FreeImage_ZLibCompress(uint8_t *target, DWORD target_size, uint8_t *source, DWORD source_size) {
uLongf dest_len = (uLongf)target_size;
int zerr = compress(target, &dest_len, source, source_size);
switch(zerr) {
case Z_MEM_ERROR: // not enough memory
case Z_BUF_ERROR: // not enough room in the output buffer
FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
return 0;
case Z_OK:
return dest_len;
}
return 0;
}
/**
Decompresses a source buffer into a target buffer, using the ZLib library.
Upon entry, target_size is the total size of the destination buffer,
which must be large enough to hold the entire uncompressed data.
The size of the uncompressed data must have been saved previously by the compressor
and transmitted to the decompressor by some mechanism outside the scope of this
compression library.
@param target Destination buffer
@param target_size Size of the destination buffer, in bytes
@param source Source buffer
@param source_size Size of the source buffer, in bytes
@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured
@see FreeImage_ZLibCompress
*/
DWORD DLL_CALLCONV
FreeImage_ZLibUncompress(uint8_t *target, DWORD target_size, uint8_t *source, DWORD source_size) {
uLongf dest_len = (uLongf)target_size;
int zerr = uncompress(target, &dest_len, source, source_size);
switch(zerr) {
case Z_MEM_ERROR: // not enough memory
case Z_BUF_ERROR: // not enough room in the output buffer
case Z_DATA_ERROR: // input data was corrupted
FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
return 0;
case Z_OK:
return dest_len;
}
return 0;
}
/**
Compresses a source buffer into a target buffer, using the ZLib library.
On success, the target buffer contains a GZIP compatible layout.
Upon entry, target_size is the total size of the destination buffer,
which must be at least 0.1% larger than source_size plus 24 bytes.
@param target Destination buffer
@param target_size Size of the destination buffer, in bytes
@param source Source buffer
@param source_size Size of the source buffer, in bytes
@return Returns the actual size of the compressed buffer, returns 0 if an error occured
@see FreeImage_ZLibCompress
*/
DWORD DLL_CALLCONV
FreeImage_ZLibGZip(uint8_t *target, DWORD target_size, uint8_t *source, DWORD source_size) {
uLongf dest_len = (uLongf)target_size - 12;
DWORD crc = crc32(0L, NULL, 0);
// set up header (stolen from zlib/gzio.c)
sprintf((char *)target, "%c%c%c%c%c%c%c%c", 0x1f, 0x8b,
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/);
int zerr = compress2(target + 8, &dest_len, source, source_size, Z_BEST_COMPRESSION);
switch(zerr) {
case Z_MEM_ERROR: // not enough memory
case Z_BUF_ERROR: // not enough room in the output buffer
FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
return 0;
case Z_OK: {
// patch header, setup crc and length (stolen from mod_trace_output)
uint8_t *p = target + 8; *p++ = 2; *p = OS_CODE; // xflags, os_code
crc = crc32(crc, source, source_size);
memcpy(target + 4 + dest_len, &crc, 4);
memcpy(target + 8 + dest_len, &source_size, 4);
return dest_len + 12;
}
}
return 0;
}
/**
Decompresses a gzipped source buffer into a target buffer, using the ZLib library.
Upon entry, target_size is the total size of the destination buffer,
which must be large enough to hold the entire uncompressed data.
The size of the uncompressed data must have been saved previously by the compressor
and transmitted to the decompressor by some mechanism outside the scope of this
compression library.
@param target Destination buffer
@param target_size Size of the destination buffer, in bytes
@param source Source buffer
@param source_size Size of the source buffer, in bytes
@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured
@see FreeImage_ZLibGZip
*/
static int get_byte(z_stream *stream) {
if (stream->avail_in <= 0) return EOF;
stream->avail_in--;
return *(stream->next_in)++;
}
static int checkheader(z_stream *stream) {
int flags, c;
DWORD len;
if (get_byte(stream) != 0x1f || get_byte(stream) != 0x8b)
return Z_DATA_ERROR;
if (get_byte(stream) != Z_DEFLATED || ((flags = get_byte(stream)) & 0xE0) != 0)
return Z_DATA_ERROR;
for (len = 0; len < 6; len++) (void)get_byte(stream);
if ((flags & 0x04) != 0) { /* skip the extra field */
len = (DWORD)get_byte(stream);
len += ((DWORD)get_byte(stream)) << 8;
/* len is garbage if EOF but the loop below will quit anyway */
while (len-- != 0 && get_byte(stream) != EOF) ;
}
if ((flags & 0x08) != 0) { /* skip the original file name */
while ((c = get_byte(stream)) != 0 && c != EOF) ;
}
if ((flags & 0x10) != 0) { /* skip the .gz file comment */
while ((c = get_byte(stream)) != 0 && c != EOF) ;
}
if ((flags & 0x02) != 0) { /* skip the header crc */
for (len = 0; len < 2; len++) (void)get_byte(stream);
}
return Z_OK;
}
DWORD DLL_CALLCONV
FreeImage_ZLibGUnzip(uint8_t *target, DWORD target_size, uint8_t *source, DWORD source_size) {
DWORD src_len = source_size;
DWORD dest_len = target_size;
int zerr = Z_DATA_ERROR;
if (src_len > 0) {
z_stream stream;
memset(&stream, 0, sizeof (stream));
if ((zerr = inflateInit2(&stream, -MAX_WBITS)) == Z_OK) {
stream.next_in = source;
stream.avail_in = source_size;
stream.next_out = target;
stream.avail_out = target_size;
if ((zerr = checkheader(&stream)) == Z_OK) {
zerr = inflate (&stream, Z_NO_FLUSH);
dest_len = target_size - stream.avail_out;
if (zerr == Z_OK || zerr == Z_STREAM_END)
inflateEnd(&stream);
}
}
}
if (zerr != Z_OK && zerr != Z_STREAM_END) {
FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
return 0;
}
return dest_len;
}
/**
Update a running crc from source and return the updated crc, using the ZLib library.
If source is NULL, this function returns the required initial value for the crc.
@param crc Running crc value
@param source Source buffer
@param source_size Size of the source buffer, in bytes
@return Returns the new crc value
*/
DWORD DLL_CALLCONV
FreeImage_ZLibCRC32(DWORD crc, uint8_t *source, DWORD source_size) {
return crc32(crc, source, source_size);
}
|