1 // example3.c - Demonstrates how to use miniz.c's deflate() and inflate() functions for simple file compression.
2 // Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
3 // For simplicity, this example is limited to files smaller than 4GB, but this is not a limitation of miniz.c.
4 #include <stdio.h>
5 #include <limits.h>
6 #include "miniz.h"
7
8 typedef unsigned char uint8;
9 typedef unsigned short uint16;
10 typedef unsigned int uint;
11
12 #define my_max(a,b) (((a) > (b)) ? (a) : (b))
13 #define my_min(a,b) (((a) < (b)) ? (a) : (b))
14
15 #define BUF_SIZE (1024 * 1024)
16 static uint8 s_inbuf[BUF_SIZE];
17 static uint8 s_outbuf[BUF_SIZE];
18
main(int argc,char * argv[])19 int main(int argc, char *argv[])
20 {
21 const char *pMode;
22 FILE *pInfile, *pOutfile;
23 uint infile_size;
24 int level = Z_BEST_COMPRESSION;
25 z_stream stream;
26 int p = 1;
27 const char *pSrc_filename;
28 const char *pDst_filename;
29 long file_loc;
30
31 printf("miniz.c version: %s\n", MZ_VERSION);
32
33 if (argc < 4)
34 {
35 printf("Usage: example3 [options] [mode:c or d] infile outfile\n");
36 printf("\nModes:\n");
37 printf("c - Compresses file infile to a zlib stream in file outfile\n");
38 printf("d - Decompress zlib stream in file infile to file outfile\n");
39 printf("\nOptions:\n");
40 printf("-l[0-10] - Compression level, higher values are slower.\n");
41 return EXIT_FAILURE;
42 }
43
44 while ((p < argc) && (argv[p][0] == '-'))
45 {
46 switch (argv[p][1])
47 {
48 case 'l':
49 {
50 level = atoi(&argv[1][2]);
51 if ((level < 0) || (level > 10))
52 {
53 printf("Invalid level!\n");
54 return EXIT_FAILURE;
55 }
56 break;
57 }
58 default:
59 {
60 printf("Invalid option: %s\n", argv[p]);
61 return EXIT_FAILURE;
62 }
63 }
64 p++;
65 }
66
67 if ((argc - p) < 3)
68 {
69 printf("Must specify mode, input filename, and output filename after options!\n");
70 return EXIT_FAILURE;
71 }
72 else if ((argc - p) > 3)
73 {
74 printf("Too many filenames!\n");
75 return EXIT_FAILURE;
76 }
77
78 pMode = argv[p++];
79 if (!strchr("cCdD", pMode[0]))
80 {
81 printf("Invalid mode!\n");
82 return EXIT_FAILURE;
83 }
84
85 pSrc_filename = argv[p++];
86 pDst_filename = argv[p++];
87
88 printf("Mode: %c, Level: %u\nInput File: \"%s\"\nOutput File: \"%s\"\n", pMode[0], level, pSrc_filename, pDst_filename);
89
90 // Open input file.
91 pInfile = fopen(pSrc_filename, "rb");
92 if (!pInfile)
93 {
94 printf("Failed opening input file!\n");
95 return EXIT_FAILURE;
96 }
97
98 // Determine input file's size.
99 fseek(pInfile, 0, SEEK_END);
100 file_loc = ftell(pInfile);
101 fseek(pInfile, 0, SEEK_SET);
102
103 if ((file_loc < 0) || (file_loc > INT_MAX))
104 {
105 // This is not a limitation of miniz or tinfl, but this example.
106 printf("File is too large to be processed by this example.\n");
107 return EXIT_FAILURE;
108 }
109
110 infile_size = (uint)file_loc;
111
112 // Open output file.
113 pOutfile = fopen(pDst_filename, "wb");
114 if (!pOutfile)
115 {
116 printf("Failed opening output file!\n");
117 return EXIT_FAILURE;
118 }
119
120 printf("Input file size: %u\n", infile_size);
121
122 // Init the z_stream
123 memset(&stream, 0, sizeof(stream));
124 stream.next_in = s_inbuf;
125 stream.avail_in = 0;
126 stream.next_out = s_outbuf;
127 stream.avail_out = BUF_SIZE;
128
129 if ((pMode[0] == 'c') || (pMode[0] == 'C'))
130 {
131 // Compression.
132 uint infile_remaining = infile_size;
133
134 if (deflateInit(&stream, level) != Z_OK)
135 {
136 printf("deflateInit() failed!\n");
137 return EXIT_FAILURE;
138 }
139
140 for ( ; ; )
141 {
142 int status;
143 if (!stream.avail_in)
144 {
145 // Input buffer is empty, so read more bytes from input file.
146 uint n = my_min(BUF_SIZE, infile_remaining);
147
148 if (fread(s_inbuf, 1, n, pInfile) != n)
149 {
150 printf("Failed reading from input file!\n");
151 return EXIT_FAILURE;
152 }
153
154 stream.next_in = s_inbuf;
155 stream.avail_in = n;
156
157 infile_remaining -= n;
158 //printf("Input bytes remaining: %u\n", infile_remaining);
159 }
160
161 status = deflate(&stream, infile_remaining ? Z_NO_FLUSH : Z_FINISH);
162
163 if ((status == Z_STREAM_END) || (!stream.avail_out))
164 {
165 // Output buffer is full, or compression is done, so write buffer to output file.
166 uint n = BUF_SIZE - stream.avail_out;
167 if (fwrite(s_outbuf, 1, n, pOutfile) != n)
168 {
169 printf("Failed writing to output file!\n");
170 return EXIT_FAILURE;
171 }
172 stream.next_out = s_outbuf;
173 stream.avail_out = BUF_SIZE;
174 }
175
176 if (status == Z_STREAM_END)
177 break;
178 else if (status != Z_OK)
179 {
180 printf("deflate() failed with status %i!\n", status);
181 return EXIT_FAILURE;
182 }
183 }
184
185 if (deflateEnd(&stream) != Z_OK)
186 {
187 printf("deflateEnd() failed!\n");
188 return EXIT_FAILURE;
189 }
190 }
191 else if ((pMode[0] == 'd') || (pMode[0] == 'D'))
192 {
193 // Decompression.
194 uint infile_remaining = infile_size;
195
196 if (inflateInit(&stream))
197 {
198 printf("inflateInit() failed!\n");
199 return EXIT_FAILURE;
200 }
201
202 for ( ; ; )
203 {
204 int status;
205 if (!stream.avail_in)
206 {
207 // Input buffer is empty, so read more bytes from input file.
208 uint n = my_min(BUF_SIZE, infile_remaining);
209
210 if (fread(s_inbuf, 1, n, pInfile) != n)
211 {
212 printf("Failed reading from input file!\n");
213 return EXIT_FAILURE;
214 }
215
216 stream.next_in = s_inbuf;
217 stream.avail_in = n;
218
219 infile_remaining -= n;
220 }
221
222 status = inflate(&stream, Z_SYNC_FLUSH);
223
224 if ((status == Z_STREAM_END) || (!stream.avail_out))
225 {
226 // Output buffer is full, or decompression is done, so write buffer to output file.
227 uint n = BUF_SIZE - stream.avail_out;
228 if (fwrite(s_outbuf, 1, n, pOutfile) != n)
229 {
230 printf("Failed writing to output file!\n");
231 return EXIT_FAILURE;
232 }
233 stream.next_out = s_outbuf;
234 stream.avail_out = BUF_SIZE;
235 }
236
237 if (status == Z_STREAM_END)
238 break;
239 else if (status != Z_OK)
240 {
241 printf("inflate() failed with status %i!\n", status);
242 return EXIT_FAILURE;
243 }
244 }
245
246 if (inflateEnd(&stream) != Z_OK)
247 {
248 printf("inflateEnd() failed!\n");
249 return EXIT_FAILURE;
250 }
251 }
252 else
253 {
254 printf("Invalid mode!\n");
255 return EXIT_FAILURE;
256 }
257
258 fclose(pInfile);
259 if (EOF == fclose(pOutfile))
260 {
261 printf("Failed writing to output file!\n");
262 return EXIT_FAILURE;
263 }
264
265 printf("Total input bytes: %u\n", (mz_uint32)stream.total_in);
266 printf("Total output bytes: %u\n", (mz_uint32)stream.total_out);
267 printf("Success.\n");
268 return EXIT_SUCCESS;
269 }
270