-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathmtpng.h
542 lines (493 loc) · 15.9 KB
/
mtpng.h
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
//
// mtpng - a multithreaded parallel PNG encoder in Rust
// mtpng.h - C API header
//
// Copyright (c) 2018-2024 Brooke Vibber
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#ifndef MTPNG_H_INCLUDED
#define MTPNG_H_INCLUDED 1
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#pragma mark Consts and enums
//
// Pass to mtpng_threadpool_new() as number of threads to
// use the default, which is the detected number of logical
// CPU cores on the system.
//
#define MTPNG_THREADS_DEFAULT 0
//
// Return type for mtpng functions.
// Always check the return value, errors are real!
//
typedef enum mtpng_result_t {
MTPNG_RESULT_OK = 0,
MTPNG_RESULT_ERR = 1
} mtpng_result;
//
// Filter types for mtpng_encoder_set_filter_mode().
//
// MTPNG_FILTER_ADAPTIVE is the default behavior, which uses
// a heuristic to try to guess the best compressing filter.
//
typedef enum mtpng_filter_t {
MTPNG_FILTER_ADAPTIVE = -1,
MTPNG_FILTER_NONE = 0,
MTPNG_FILTER_SUB = 1,
MTPNG_FILTER_UP = 2,
MTPNG_FILTER_AVERAGE = 3,
MTPNG_FILTER_PAETH = 4
} mtpng_filter;
//
// Strategy types for mtpng_encoder_set_strategy_mode().
//
// MTPNG_STRATEGY_ADAPTIVE is the default behavior.
//
typedef enum mtpng_strategy_t {
MTPNG_STRATEGY_ADAPTIVE = -1,
MTPNG_STRATEGY_DEFAULT = 0,
MTPNG_STRATEGY_FILTERED = 1,
MTPNG_STRATEGY_HUFFMAN = 2,
MTPNG_STRATEGY_RLE = 3,
MTPNG_STRATEGY_FIXED = 4
} mtpng_strategy;
//
// Compression levels for mtpng_encoder_options_set_compression_level().
//
typedef enum mtpng_compression_level_t {
MTPNG_COMPRESSION_LEVEL_FAST = 1,
MTPNG_COMPRESSION_LEVEL_DEFAULT = 6,
MTPNG_COMPRESSION_LEVEL_HIGH = 9
} mtpng_compression_level;
//
// Color types for mtpng_encoder_set_color().
//
typedef enum mtpng_color_t {
MTPNG_COLOR_GREYSCALE = 0,
MTPNG_COLOR_TRUECOLOR = 2,
MTPNG_COLOR_INDEXED_COLOR = 3,
MTPNG_COLOR_GREYSCALE_ALPHA = 4,
MTPNG_COLOR_TRUECOLOR_ALPHA = 6
} mtpng_color;
#pragma mark Structs
//
// Represents a thread pool, which may be shared between
// multiple encoders at once or over time.
//
// The contents are private; you will only ever use pointers.
//
typedef struct mtpng_threadpool_struct mtpng_threadpool;
//
// Represents configuration options for the PNG encoder.
//
// The contents are private; you will only ever use pointers.
//
typedef struct mtpng_encoder_options_struct mtpng_encoder_options;
//
// Represents a PNG image's top-level metadata, belonging
// in the iHDR header chunk.
//
// The contents are private; you will only ever use pointers.
//
typedef struct mtpng_header_struct mtpng_header;
//
// Represents a PNG encoder instance, which can encode a single
// image and then must be released. Multiple encoders may share
// a single thread pool.
//
// The contents are private; you will only ever use pointers.
//
typedef struct mtpng_encoder_struct mtpng_encoder;
#pragma mark Function types
#if 0
//
// Read callback type for mtpng_decoder_new().
//
// When additional input data is required, this callback is given
// a data buffer to copy into. If data is not yet available, you
// should block until it is.
//
// Return the number of bytes copied, or less on end of file or
// failure.
//
typedef size_t (*mtpng_read_func)(void* user_data,
uint8_t* p_bytes,
size_t len);
#endif
//
// Write callback type for mtpng_encoder_new().
//
// When output data is available from the decoder, it is sent to this
// callback where you may write it to a file, network socket, memory
// buffer, etc.
//
// Return the number of bytes written, or less on failure.
//
// Callbacks must report all provided data written to be considered
// successful; failure will propagate to abort the encoding process.
//
typedef size_t (*mtpng_write_func)(void* user_data,
const uint8_t* p_bytes,
size_t len);
//
// Flush callback type for mtpng_encoder_new().
//
// If buffering output to a socket or file, you should flush it
// at this point.
//
// This may be called when streaming output at block boundaries,
// allowing a realtime consumer of the data to see and decode
// the additional data.
//
// Return true on success, or false on failure; failure will
// propagate to abort the encoding process.
//
typedef bool (*mtpng_flush_func)(void* user_data);
#pragma mark ThreadPool
//
// Creates a new thread pool with the given number of threads.
// MTPNG_THREADS_DEFAULT (0) means to auto-detect the number of
// logical processors.
//
// On input, *pp_pool must be NULL.
// On output, *pp_pool will be a pointer to a thread pool instance
// if successful, or remain unchanged in case of error.
//
// If you do not create a thread pool, a default global one will
// be created when you first create an encoder.
//
// A thread pool may be used with multiple encoders, but caller
// is responsible for ensuring that the pool lives longer than
// all the encoders using it.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_threadpool_new(mtpng_threadpool** pp_pool,
size_t threads);
//
// Releases the pool's memory and clears the pointer.
//
// On input, *pp_pool must be a valid instance pointer.
// On output, *pp_pool will be NULL on success or remain unchanged
// in case of failure.
//
// Caller's responsibility to ensure that no encoders are using
// the pool.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_threadpool_release(mtpng_threadpool** pp_pool);
#pragma mark Encoder options
//
// Creates a new set of encoder options. Fill out the details
// and pass in to mtpng_encoder_new(). May be reused on multiple
// encoders.
//
// Free with mtpng_encoder_options_release().
//
// On input, *pp_options must be NULL.
// On output, *pp_options will be a pointer to an options instance
// if successful, or remain unchanged in case of error.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_options_new(mtpng_encoder_options** pp_options);
//
// Releases the option set's memory and clears the pointer.
//
// On input, *pp_options must be a valid instance pointer.
// On output, *pp_options will be NULL on success or remain unchanged
// in case of failure.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_options_release(mtpng_encoder_options** pp_options);
//
// Set the thread pool instance to queue work on.
//
// p_pool may be NULL, in which case a default global thread pool
// will be used. If a thread pool is provided, it is the caller's
// responsibility to keep the thread pool alive until all encoders
// using it have been released.
//
// Check the return values for errors.
//
extern mtpng_result
mtpng_encoder_options_set_thread_pool(mtpng_encoder_options* p_options,
mtpng_threadpool* p_pool);
//
// Override the default PNG filter mode selection.
//
// The default is MTPNG_FILTER_NONE for indexed images and
// MTPNG_FILTER_ADAPTIVE for all others. Some images compress
// better with a particular filter.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_options_set_filter(mtpng_encoder_options* p_options,
mtpng_filter filter_mode);
//
// Override the default PNG strategy mode selection.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_options_set_strategy(mtpng_encoder_options* p_options,
mtpng_strategy strategy_mode);
//
// Override the default PNG compression level.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_options_set_compression_level(mtpng_encoder_options* p_options,
mtpng_compression_level compression_level);
//
// Override the default chunk size for parallel encoding
// of larger files. Actual chunking will be in terms of
// rows, so data chunks will be at least the given size
// in bytes.
//
// If there are more chunks in the image's raw data bytes
// than available CPUs on the thread pool, you should see
// parallel speedups as long as input data is provided
// fast enough.
//
// If the file is smaller than the chunk size, currently
// the speed will be equivalent to running single-threaded.
//
// chunk_size must be at least 32768 bytes, required for
// maintaining compression across chunks.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_options_set_chunk_size(mtpng_encoder_options* p_options,
size_t chunk_size);
#pragma mark Header
//
// Creates a new PNG header with default settings. Fill out the details
// and pass in to mtpng_encoder_write_header(). May be reused on multiple
// encoders.
//
// Free with mtpng_header_release().
//
// On input, *pp_header must be NULL.
// On output, *pp_header will be a pointer to an options instance
// if successful, or remain unchanged in case of error.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_header_new(mtpng_header** pp_header);
//
// Releases the header's memory and clears the pointer.
//
// On input, *pp_header must be a valid instance pointer.
// On output, *pp_header will be NULL on success or remain unchanged
// in case of failure.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_header_release(mtpng_header** pp_header);
//
// Set the image size in pixels. The given width and height
// values must not be 0, but are not otherwise limited.
//
// Caller is responsible for ensuring that at least one row
// of image data copied a few times fits in memory, or you're
// gonna have a bad time.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_header_set_size(mtpng_header* p_header,
uint32_t width,
uint32_t height);
//
// Set the color type and depth for the image.
//
// Any valid combination of color type and depth is accepted;
// see https://www.w3.org/TR/PNG/#table111 for the specs.
//
// If you do not call this function, mtpng will assume you want
// truecolor with alpha at 8-bit depth.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_header_set_color(mtpng_header* p_header,
mtpng_color color_type,
uint8_t depth);
#pragma mark Encoder
//
// Create a new PNG encoder instance.
// Copies the options data.
//
// On input, *pp_encoder must be NULL.
// On output, *pp_encoder will be an instance pointer on success,
// or remain unchanged in case of failure.
//
// The write_func and flush_func callbacks are required, and must
// not be NULL.
//
// user_data is passed to the callback functions, and may be any
// value such as a private object pointer or NULL.
//
// p_options may be NULL, in which case default options will
// be used including a global threadpool.
//
// Check the return values for errors.
//
extern mtpng_result
mtpng_encoder_new(mtpng_encoder** pp_encoder,
mtpng_write_func write_func,
mtpng_flush_func flush_func,
void* const user_data,
mtpng_encoder_options* p_options);
//
// Releases the encoder's memory and clears the pointer.
//
// This need only be used if aborting encoding early due to
// errors etc; normally the call to mtpng_encoder_finish()
// at the end of encoding will consume the instance and
// release its memory.
//
// On input, *pp_encoder must be a valid instance pointer.
// On output, *pp_encoder will be NULL on success, or remain
// unchanged in case of failure.
//
// If using a threadpool, must be called before releasing the
// threadpool!
//
// If the encoder is still in use, this may explode.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_release(mtpng_encoder** pp_encoder);
//
// Signal that we're done setting up, and start writing
// header data to the output.
//
// Must be called before mtpng_encoder_append_row() or
// mtpng_encoder_finish().
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_write_header(mtpng_encoder* p_encoder,
mtpng_header* p_header);
//
// Write a palette entry for an indexed-color image, or a
// suggested quantization palette for a truecolor image.
//
// See https://www.w3.org/TR/PNG/#11PLTE for the data format.
//
// Must be called after mtpng_encoder_write_header() and before
// mtpng_encoder_write_image() or mtpng_encoder_write_image_data().
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_write_palette(mtpng_encoder* p_encoder,
const uint8_t* p_bytes,
size_t len);
//
// Write alpha transparency entries for an indexed-color image, or a
// single transparent color for a greyscale or truecolor image.
//
// See https://www.w3.org/TR/PNG/#11tRNS for the data format.
//
// Must be called after mtpng_encoder_write_palette() for indexed
// images, or mtpng_encoder_write_header() for others; and before
// mtpng_encoder_write_image() or mtpng_encoder_write_image_data().
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_write_transparency(mtpng_encoder* p_encoder,
const uint8_t* p_bytes,
size_t len);
//
// Write a custom ancillary chunk to the output stream.
// The tag must be a 4-byte string. The data should be provided
// in the appropriate format for the tag.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_write_chunk(mtpng_encoder* p_encoder,
const char* p_tag,
const uint8_t* p_bytes,
size_t len);
//
// Load one or more rows of input data into the encoder, to be
// filtered and compressed as data is provided.
//
// Must be called after mtpng_encoder_write_header() and before
// mtpng_encoder_finish().
//
// Image data must be pre-packed in the correct bit depth and
// channel order. If not all rows are provided before calling
// mtpng_encoder_finish(), failure will result.
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_write_image_rows(mtpng_encoder* p_encoder,
const uint8_t* p_bytes,
size_t len);
//
// Wait for any outstanding work blocks, flush output,
// release the encoder instance and clear the pointer.
//
// Must be called after all rows have been appended with
// mtpng_encoder_append_row().
//
// On input, *pp_encoder must be a valid instance pointer.
// On output, *pp_encoder will be NULL on success, or remain
// unchanged in case of failure.
//
// You do not need to call mtpng_encoder_release after
// this returns, and should not try.
//
// If using a threadpool, must be called before releasing
// the threadpool!
//
// Check the return value for errors.
//
extern mtpng_result
mtpng_encoder_finish(mtpng_encoder** pp_encoder);
#pragma mark footer
#ifdef __cplusplus
}
#endif
#endif /* MTPNG_H_INCLUDED */