example3.c 6.6 KB

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