1 #pragma once
2 #include "miniz_common.h"
3 
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7 /* ------------------- Low-level Compression API Definitions */
8 
9 /* Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). */
10 #define TDEFL_LESS_MEMORY 0
11 
12 /* tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): */
13 /* TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). */
14 enum
15 {
16     TDEFL_HUFFMAN_ONLY = 0,
17     TDEFL_DEFAULT_MAX_PROBES = 128,
18     TDEFL_MAX_PROBES_MASK = 0xFFF
19 };
20 
21 /* TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. */
22 /* TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). */
23 /* TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. */
24 /* TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). */
25 /* TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) */
26 /* TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. */
27 /* TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. */
28 /* TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. */
29 /* The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). */
30 enum
31 {
32     TDEFL_WRITE_ZLIB_HEADER = 0x01000,
33     TDEFL_COMPUTE_ADLER32 = 0x02000,
34     TDEFL_GREEDY_PARSING_FLAG = 0x04000,
35     TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
36     TDEFL_RLE_MATCHES = 0x10000,
37     TDEFL_FILTER_MATCHES = 0x20000,
38     TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
39     TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
40 };
41 
42 /* High level compression functions: */
43 /* tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). */
44 /* On entry: */
45 /*  pSrc_buf, src_buf_len: Pointer and size of source block to compress. */
46 /*  flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. */
47 /* On return: */
48 /*  Function returns a pointer to the compressed data, or NULL on failure. */
49 /*  *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. */
50 /*  The caller must free() the returned block when it's no longer needed. */
51 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
52 
53 /* tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. */
54 /* Returns 0 on failure. */
55 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
56 
57 /* Compresses an image to a compressed PNG file in memory. */
58 /* On entry: */
59 /*  pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. */
60 /*  The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. */
61 /*  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL */
62 /*  If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). */
63 /* On return: */
64 /*  Function returns a pointer to the compressed data, or NULL on failure. */
65 /*  *pLen_out will be set to the size of the PNG image file. */
66 /*  The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. */
67 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
68 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
69 
70 /* Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. */
71 typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
72 
73 /* tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. */
74 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
75 
76 enum
77 {
78     TDEFL_MAX_HUFF_TABLES = 3,
79     TDEFL_MAX_HUFF_SYMBOLS_0 = 288,
80     TDEFL_MAX_HUFF_SYMBOLS_1 = 32,
81     TDEFL_MAX_HUFF_SYMBOLS_2 = 19,
82     TDEFL_LZ_DICT_SIZE = 32768,
83     TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1,
84     TDEFL_MIN_MATCH_LEN = 3,
85     TDEFL_MAX_MATCH_LEN = 258
86 };
87 
88 /* TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). */
89 #if TDEFL_LESS_MEMORY
90 enum
91 {
92     TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024,
93     TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
94     TDEFL_MAX_HUFF_SYMBOLS = 288,
95     TDEFL_LZ_HASH_BITS = 12,
96     TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
97     TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
98     TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
99 };
100 #else
101 enum
102 {
103     TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024,
104     TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
105     TDEFL_MAX_HUFF_SYMBOLS = 288,
106     TDEFL_LZ_HASH_BITS = 15,
107     TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
108     TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
109     TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
110 };
111 #endif
112 
113 /* The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. */
114 typedef enum {
115     TDEFL_STATUS_BAD_PARAM = -2,
116     TDEFL_STATUS_PUT_BUF_FAILED = -1,
117     TDEFL_STATUS_OKAY = 0,
118     TDEFL_STATUS_DONE = 1
119 } tdefl_status;
120 
121 /* Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums */
122 typedef enum {
123     TDEFL_NO_FLUSH = 0,
124     TDEFL_SYNC_FLUSH = 2,
125     TDEFL_FULL_FLUSH = 3,
126     TDEFL_FINISH = 4
127 } tdefl_flush;
128 
129 /* tdefl's compression state structure. */
130 typedef struct
131 {
132     tdefl_put_buf_func_ptr m_pPut_buf_func;
133     void *m_pPut_buf_user;
134     mz_uint m_flags, m_max_probes[2];
135     int m_greedy_parsing;
136     mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
137     mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
138     mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
139     mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
140     tdefl_status m_prev_return_status;
141     const void *m_pIn_buf;
142     void *m_pOut_buf;
143     size_t *m_pIn_buf_size, *m_pOut_buf_size;
144     tdefl_flush m_flush;
145     const mz_uint8 *m_pSrc;
146     size_t m_src_buf_left, m_out_buf_ofs;
147     mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
148     mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
149     mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
150     mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
151     mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
152     mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
153     mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
154     mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
155 } tdefl_compressor;
156 
157 /* Initializes the compressor. */
158 /* There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. */
159 /* pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. */
160 /* If pBut_buf_func is NULL the user should always call the tdefl_compress() API. */
161 /* flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) */
162 tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
163 
164 /* Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. */
165 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
166 
167 /* tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. */
168 /* tdefl_compress_buffer() always consumes the entire input buffer. */
169 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
170 
171 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
172 mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
173 
174 /* Create tdefl_compress() flags given zlib-style compression parameters. */
175 /* level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) */
176 /* window_bits may be -15 (raw deflate) or 15 (zlib) */
177 /* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */
178 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
179 
180 /* Allocate the tdefl_compressor structure in C so that */
181 /* non-C language bindings to tdefl_ API don't need to worry about */
182 /* structure size and allocation mechanism. */
183 tdefl_compressor *tdefl_compressor_alloc();
184 void tdefl_compressor_free(tdefl_compressor *pComp);
185 
186 #ifdef __cplusplus
187 }
188 #endif
189