/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/ZLibInterface.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // ========================================================== |
2 | | // ZLib library interface |
3 | | // |
4 | | // Design and implementation by |
5 | | // - Floris van den Berg (flvdberg@wxs.nl) |
6 | | // |
7 | | // This file is part of FreeImage 3 |
8 | | // |
9 | | // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY |
10 | | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES |
11 | | // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE |
12 | | // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED |
13 | | // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT |
14 | | // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY |
15 | | // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL |
16 | | // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER |
17 | | // THIS DISCLAIMER. |
18 | | // |
19 | | // Use at your own risk! |
20 | | // ========================================================== |
21 | | |
22 | | #include "../ZLib/zlib.h" |
23 | | #include "FreeImage.h" |
24 | | #include "Utilities.h" |
25 | | #include "../ZLib/zutil.h" /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */ |
26 | | |
27 | | /** |
28 | | Compresses a source buffer into a target buffer, using the ZLib library. |
29 | | Upon entry, target_size is the total size of the destination buffer, |
30 | | which must be at least 0.1% larger than source_size plus 12 bytes. |
31 | | |
32 | | @param target Destination buffer |
33 | | @param target_size Size of the destination buffer, in bytes |
34 | | @param source Source buffer |
35 | | @param source_size Size of the source buffer, in bytes |
36 | | @return Returns the actual size of the compressed buffer, returns 0 if an error occured |
37 | | @see FreeImage_ZLibUncompress |
38 | | */ |
39 | | DWORD DLL_CALLCONV |
40 | 0 | FreeImage_ZLibCompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { |
41 | 0 | uLongf dest_len = (uLongf)target_size; |
42 | |
|
43 | 0 | int zerr = compress(target, &dest_len, source, source_size); |
44 | 0 | switch(zerr) { |
45 | 0 | case Z_MEM_ERROR: // not enough memory |
46 | 0 | case Z_BUF_ERROR: // not enough room in the output buffer |
47 | 0 | FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); |
48 | 0 | return 0; |
49 | 0 | case Z_OK: |
50 | 0 | return dest_len; |
51 | 0 | } |
52 | | |
53 | 0 | return 0; |
54 | 0 | } |
55 | | |
56 | | /** |
57 | | Decompresses a source buffer into a target buffer, using the ZLib library. |
58 | | Upon entry, target_size is the total size of the destination buffer, |
59 | | which must be large enough to hold the entire uncompressed data. |
60 | | The size of the uncompressed data must have been saved previously by the compressor |
61 | | and transmitted to the decompressor by some mechanism outside the scope of this |
62 | | compression library. |
63 | | |
64 | | @param target Destination buffer |
65 | | @param target_size Size of the destination buffer, in bytes |
66 | | @param source Source buffer |
67 | | @param source_size Size of the source buffer, in bytes |
68 | | @return Returns the actual size of the uncompressed buffer, returns 0 if an error occured |
69 | | @see FreeImage_ZLibCompress |
70 | | */ |
71 | | DWORD DLL_CALLCONV |
72 | 0 | FreeImage_ZLibUncompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { |
73 | 0 | uLongf dest_len = (uLongf)target_size; |
74 | |
|
75 | 0 | int zerr = uncompress(target, &dest_len, source, source_size); |
76 | 0 | switch(zerr) { |
77 | 0 | case Z_MEM_ERROR: // not enough memory |
78 | 0 | case Z_BUF_ERROR: // not enough room in the output buffer |
79 | 0 | case Z_DATA_ERROR: // input data was corrupted |
80 | 0 | FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); |
81 | 0 | return 0; |
82 | 0 | case Z_OK: |
83 | 0 | return dest_len; |
84 | 0 | } |
85 | | |
86 | 0 | return 0; |
87 | 0 | } |
88 | | |
89 | | /** |
90 | | Compresses a source buffer into a target buffer, using the ZLib library. |
91 | | On success, the target buffer contains a GZIP compatible layout. |
92 | | Upon entry, target_size is the total size of the destination buffer, |
93 | | which must be at least 0.1% larger than source_size plus 24 bytes. |
94 | | |
95 | | @param target Destination buffer |
96 | | @param target_size Size of the destination buffer, in bytes |
97 | | @param source Source buffer |
98 | | @param source_size Size of the source buffer, in bytes |
99 | | @return Returns the actual size of the compressed buffer, returns 0 if an error occured |
100 | | @see FreeImage_ZLibCompress |
101 | | */ |
102 | | DWORD DLL_CALLCONV |
103 | 0 | FreeImage_ZLibGZip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { |
104 | 0 | uLongf dest_len = (uLongf)target_size - 12; |
105 | 0 | DWORD crc = crc32(0L, NULL, 0); |
106 | | |
107 | | // set up header (stolen from zlib/gzio.c) |
108 | 0 | sprintf((char *)target, "%c%c%c%c%c%c%c%c", 0x1f, 0x8b, |
109 | 0 | Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/); |
110 | 0 | int zerr = compress2(target + 8, &dest_len, source, source_size, Z_BEST_COMPRESSION); |
111 | 0 | switch(zerr) { |
112 | 0 | case Z_MEM_ERROR: // not enough memory |
113 | 0 | case Z_BUF_ERROR: // not enough room in the output buffer |
114 | 0 | FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); |
115 | 0 | return 0; |
116 | 0 | case Z_OK: { |
117 | | // patch header, setup crc and length (stolen from mod_trace_output) |
118 | 0 | BYTE *p = target + 8; *p++ = 2; *p = OS_CODE; // xflags, os_code |
119 | 0 | crc = crc32(crc, source, source_size); |
120 | 0 | memcpy(target + 4 + dest_len, &crc, 4); |
121 | 0 | memcpy(target + 8 + dest_len, &source_size, 4); |
122 | 0 | return dest_len + 12; |
123 | 0 | } |
124 | 0 | } |
125 | 0 | return 0; |
126 | 0 | } |
127 | | |
128 | | /** |
129 | | Decompresses a gzipped source buffer into a target buffer, using the ZLib library. |
130 | | Upon entry, target_size is the total size of the destination buffer, |
131 | | which must be large enough to hold the entire uncompressed data. |
132 | | The size of the uncompressed data must have been saved previously by the compressor |
133 | | and transmitted to the decompressor by some mechanism outside the scope of this |
134 | | compression library. |
135 | | |
136 | | @param target Destination buffer |
137 | | @param target_size Size of the destination buffer, in bytes |
138 | | @param source Source buffer |
139 | | @param source_size Size of the source buffer, in bytes |
140 | | @return Returns the actual size of the uncompressed buffer, returns 0 if an error occured |
141 | | @see FreeImage_ZLibGZip |
142 | | */ |
143 | | |
144 | 0 | static int get_byte(z_stream *stream) { |
145 | 0 | if (stream->avail_in <= 0) return EOF; |
146 | 0 | stream->avail_in--; |
147 | 0 | return *(stream->next_in)++; |
148 | 0 | } |
149 | | |
150 | 0 | static int checkheader(z_stream *stream) { |
151 | 0 | int flags, c; |
152 | 0 | DWORD len; |
153 | |
|
154 | 0 | if (get_byte(stream) != 0x1f || get_byte(stream) != 0x8b) |
155 | 0 | return Z_DATA_ERROR; |
156 | 0 | if (get_byte(stream) != Z_DEFLATED || ((flags = get_byte(stream)) & 0xE0) != 0) |
157 | 0 | return Z_DATA_ERROR; |
158 | 0 | for (len = 0; len < 6; len++) (void)get_byte(stream); |
159 | |
|
160 | 0 | if ((flags & 0x04) != 0) { /* skip the extra field */ |
161 | 0 | len = (DWORD)get_byte(stream); |
162 | 0 | len += ((DWORD)get_byte(stream)) << 8; |
163 | | /* len is garbage if EOF but the loop below will quit anyway */ |
164 | 0 | while (len-- != 0 && get_byte(stream) != EOF) ; |
165 | 0 | } |
166 | 0 | if ((flags & 0x08) != 0) { /* skip the original file name */ |
167 | 0 | while ((c = get_byte(stream)) != 0 && c != EOF) ; |
168 | 0 | } |
169 | 0 | if ((flags & 0x10) != 0) { /* skip the .gz file comment */ |
170 | 0 | while ((c = get_byte(stream)) != 0 && c != EOF) ; |
171 | 0 | } |
172 | 0 | if ((flags & 0x02) != 0) { /* skip the header crc */ |
173 | 0 | for (len = 0; len < 2; len++) (void)get_byte(stream); |
174 | 0 | } |
175 | 0 | return Z_OK; |
176 | 0 | } |
177 | | |
178 | | DWORD DLL_CALLCONV |
179 | 0 | FreeImage_ZLibGUnzip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { |
180 | 0 | DWORD src_len = source_size; |
181 | 0 | DWORD dest_len = target_size; |
182 | 0 | int zerr = Z_DATA_ERROR; |
183 | |
|
184 | 0 | if (src_len > 0) { |
185 | 0 | z_stream stream; |
186 | 0 | memset(&stream, 0, sizeof (stream)); |
187 | 0 | if ((zerr = inflateInit2(&stream, -MAX_WBITS)) == Z_OK) { |
188 | 0 | stream.next_in = source; |
189 | 0 | stream.avail_in = source_size; |
190 | |
|
191 | 0 | stream.next_out = target; |
192 | 0 | stream.avail_out = target_size; |
193 | |
|
194 | 0 | if ((zerr = checkheader(&stream)) == Z_OK) { |
195 | 0 | zerr = inflate (&stream, Z_NO_FLUSH); |
196 | 0 | dest_len = target_size - stream.avail_out; |
197 | |
|
198 | 0 | if (zerr == Z_OK || zerr == Z_STREAM_END) |
199 | 0 | inflateEnd(&stream); |
200 | 0 | } |
201 | 0 | } |
202 | 0 | } |
203 | 0 | if (zerr != Z_OK && zerr != Z_STREAM_END) { |
204 | 0 | FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); |
205 | 0 | return 0; |
206 | 0 | } |
207 | 0 | return dest_len; |
208 | 0 | } |
209 | | |
210 | | /** |
211 | | Update a running crc from source and return the updated crc, using the ZLib library. |
212 | | If source is NULL, this function returns the required initial value for the crc. |
213 | | |
214 | | @param crc Running crc value |
215 | | @param source Source buffer |
216 | | @param source_size Size of the source buffer, in bytes |
217 | | @return Returns the new crc value |
218 | | */ |
219 | | DWORD DLL_CALLCONV |
220 | 0 | FreeImage_ZLibCRC32(DWORD crc, BYTE *source, DWORD source_size) { |
221 | |
|
222 | 0 | return crc32(crc, source, source_size); |
223 | 0 | } |