HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
openexr_context.h
Go to the documentation of this file.
1 /*
2 ** SPDX-License-Identifier: BSD-3-Clause
3 ** Copyright Contributors to the OpenEXR Project.
4 */
5 
6 #ifndef OPENEXR_CONTEXT_H
7 #define OPENEXR_CONTEXT_H
8 
9 #include "openexr_errors.h"
10 
11 #include "openexr_base.h"
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 /** @file */
21 
22 /**
23  * @defgroup Context Context related definitions
24  *
25  * A context is a single instance of an OpenEXR file or stream. Beyond
26  * a particular file or stream handle, it also has separate controls
27  * for error handling and memory allocation. This is done to enable
28  * encoding or decoding on mixed hardware.
29  *
30  * @{
31  */
32 
33 /** Opaque context handle
34  *
35  * The implementation of this is partly opaque to provide better
36  * version portability, and all accesses to relevant data should
37  * happen using provided functions. This handle serves as a container
38  * and identifier for all the metadata and parts associated with a
39  * file and/or stream.
40  */
41 
42 typedef struct _priv_exr_context_t* exr_context_t;
43 typedef const struct _priv_exr_context_t* exr_const_context_t;
44 
45 /**
46  * @defgroup ContextFunctions OpenEXR Context Stream/File Functions
47  *
48  * @brief These are a group of function interfaces used to customize
49  * the error handling, memory allocations, or I/O behavior of an
50  * OpenEXR context.
51  *
52  * @{
53  */
54 
55 /** @brief Stream error notifier
56  *
57  * This function pointer is provided to the stream functions by the
58  * library such that they can provide a nice error message to the
59  * user during stream operations.
60  */
62  exr_const_context_t ctxt, exr_result_t code, const char* fmt, ...)
64 
65 /** @brief Error callback function
66  *
67  * Because a file can be read from using many threads at once, it is
68  * difficult to store an error message for later retrieval. As such,
69  * when a file is constructed, a callback function can be provided
70  * which delivers an error message for the calling application to
71  * handle. This will then be delivered on the same thread causing the
72  * error.
73  */
75  exr_const_context_t ctxt, exr_result_t code, const char* msg);
76 
77 /** Destroy custom stream function pointer
78  *
79  * Generic callback to clean up user data for custom streams.
80  * This is called when the file is closed and expected not to
81  * error.
82  *
83  * @param failed Indicates the write operation failed, the
84  * implementor may wish to cleanup temporary files
85  * @param ctxt The context
86  * @param userdata The userdata
87  */
89  exr_const_context_t ctxt, void* userdata, int failed);
90 
91 /** Query stream size function pointer
92  *
93  * Used to query the size of the file, or amount of data representing
94  * the openexr file in the data stream.
95  *
96  * This is used to validate requests against the file. If the size is
97  * unavailable, return -1, which will disable these validation steps
98  * for this file, although appropriate memory safeguards must be in
99  * place in the calling application.
100  */
101 typedef int64_t (*exr_query_size_func_ptr_t) (
102  exr_const_context_t ctxt, void* userdata);
103 
104 /** @brief Read custom function pointer
105  *
106  * Used to read data from a custom output. Expects similar semantics to
107  * pread or ReadFile with overlapped data under win32.
108  *
109  * It is required that this provides thread-safe concurrent access to
110  * the same file. If the stream/input layer you are providing does
111  * not have this guarantee, your are responsible for providing
112  * appropriate serialization of requests.
113  *
114  * A file should be expected to be accessed in the following pattern:
115  * - upon open, the header and part information attributes will be read
116  * - upon the first image read request, the offset tables will be read
117  * multiple threads accessing this concurrently may actually read
118  * these values at the same time
119  * - chunks can then be read in any order as preferred by the
120  * application
121  *
122  * While this should mean that the header will be read in 'stream'
123  * order (no seeks required), no guarantee is made beyond that to
124  * retrieve image/deep data in order. So if the backing file is
125  * truly a stream, it is up to the provider to implement appropriate
126  * caching of data to give the appearance of being able to seek/read
127  * atomically.
128  */
129 typedef int64_t (*exr_read_func_ptr_t) (
130  exr_const_context_t ctxt,
131  void* userdata,
132  void* buffer,
133  uint64_t sz,
134  uint64_t offset,
135  exr_stream_error_func_ptr_t error_cb);
136 
137 /** Write custom function pointer
138  *
139  * Used to write data to a custom output. Expects similar semantics to
140  * pwrite or WriteFile with overlapped data under win32.
141  *
142  * It is required that this provides thread-safe concurrent access to
143  * the same file. While it is unlikely that multiple threads will
144  * be used to write data for compressed forms, it is possible.
145  *
146  * A file should be expected to be accessed in the following pattern:
147  * - upon open, the header and part information attributes is constructed.
148  *
149  * - when the write_header routine is called, the header becomes immutable
150  * and is written to the file. This computes the space to store the chunk
151  * offsets, but does not yet write the values.
152  *
153  * - Image chunks are written to the file, and appear in the order
154  * they are written, not in the ordering that is required by the
155  * chunk offset table (unless written in that order). This may vary
156  * slightly if the size of the chunks is not directly known and
157  * tight packing of data is necessary.
158  *
159  * - at file close, the chunk offset tables are written to the file.
160  */
161 typedef int64_t (*exr_write_func_ptr_t) (
162  exr_const_context_t ctxt,
163  void* userdata,
164  const void* buffer,
165  uint64_t sz,
166  uint64_t offset,
167  exr_stream_error_func_ptr_t error_cb);
168 
169 /** @brief Struct used to pass function pointers into the context
170  * initialization routines.
171  *
172  * This partly exists to avoid the chicken and egg issue around
173  * creating the storage needed for the context on systems which want
174  * to override the malloc/free routines.
175  *
176  * However, it also serves to make a tidier/simpler set of functions
177  * to create and start processing exr files.
178  *
179  * The size member is required for version portability.
180  *
181  * It can be initialized using \c EXR_DEFAULT_CONTEXT_INITIALIZER.
182  *
183  * \code{.c}
184  * exr_context_initializer_t myctxtinit = DEFAULT_CONTEXT_INITIALIZER;
185  * myctxtinit.error_cb = &my_super_cool_error_callback_function;
186  * ...
187  * \endcode
188  *
189  */
191 {
192  /** @brief Size member to tag initializer for version stability.
193  *
194  * This should be initialized to the size of the current
195  * structure. This allows EXR to add functions or other
196  * initializers in the future, and retain version compatibility
197  */
198  size_t size;
199 
200  /** @brief Error callback function pointer
201  *
202  * The error callback is allowed to be `NULL`, and will use a
203  * default print which outputs to \c stderr.
204  *
205  * @sa exr_error_handler_cb_t
206  */
208 
209  /** Custom allocator, if `NULL`, will use malloc. @sa exr_memory_allocation_func_t */
211 
212  /** Custom deallocator, if `NULL`, will use free. @sa exr_memory_free_func_t */
214 
215  /** Blind data passed to custom read, size, write, destroy
216  * functions below. Up to user to manage this pointer.
217  */
218  void* user_data;
219 
220  /** @brief Custom read routine.
221  *
222  * This is only used during read or update contexts. If this is
223  * provided, it is expected that the caller has previously made
224  * the stream available, and placed whatever stream/file data
225  * into \c user_data above.
226  *
227  * If this is `NULL`, and the context requested is for reading an
228  * exr file, an internal implementation is provided for reading
229  * from normal filesystem files, and the filename provided is
230  * attempted to be opened as such.
231  *
232  * Expected to be `NULL` for a write-only operation, but is ignored
233  * if it is provided.
234  *
235  * For update contexts, both read and write functions must be
236  * provided if either is.
237  *
238  * @sa exr_read_func_ptr_t
239  */
241 
242  /** @brief Custom size query routine.
243  *
244  * Used to provide validation when reading header values. If this
245  * is not provided, but a custom read routine is provided, this
246  * will disable some of the validation checks when parsing the
247  * image header.
248  *
249  * Expected to be `NULL` for a write-only operation, but is ignored
250  * if it is provided.
251  *
252  * @sa exr_query_size_func_ptr_t
253  */
255 
256  /** @brief Custom write routine.
257  *
258  * This is only used during write or update contexts. If this is
259  * provided, it is expected that the caller has previously made
260  * the stream available, and placed whatever stream/file data
261  * into \c user_data above.
262  *
263  * If this is `NULL`, and the context requested is for writing an
264  * exr file, an internal implementation is provided for reading
265  * from normal filesystem files, and the filename provided is
266  * attempted to be opened as such.
267  *
268  * For update contexts, both read and write functions must be
269  * provided if either is.
270  *
271  * @sa exr_write_func_ptr_t
272  */
274 
275  /** @brief Optional function to destroy the user data block of a custom stream.
276  *
277  * Allows one to free any user allocated data, and close any handles.
278  *
279  * @sa exr_destroy_stream_func_ptr_t
280  * */
282 
283  /** Initialize a field specifying what the maximum image width
284  * allowed by the context is. See exr_set_default_maximum_image_size() to
285  * understand how this interacts with global defaults.
286  */
288 
289  /** Initialize a field specifying what the maximum image height
290  * allowed by the context is. See exr_set_default_maximum_image_size() to
291  * understand how this interacts with global defaults.
292  */
294 
295  /** Initialize a field specifying what the maximum tile width
296  * allowed by the context is. See exr_set_default_maximum_tile_size() to
297  * understand how this interacts with global defaults.
298  */
300 
301  /** Initialize a field specifying what the maximum tile height
302  * allowed by the context is. See exr_set_default_maximum_tile_size() to
303  * understand how this interacts with global defaults.
304  */
306 
307  /** Initialize a field specifying what the default zip compression level should be
308  * for this context. See exr_set_default_zip_compresion_level() to
309  * set it for all contexts.
310  */
312 
313  /** Initialize the default dwa compression quality. See
314  * exr_set_default_dwa_compression_quality() to set the default
315  * for all contexts.
316  */
317  float dwa_quality;
318 
319  /** Initialize with a bitwise or of the various context flags
320  */
321  int flags;
322 
323  uint8_t pad[4];
325 
326 /** @brief context flag which will enforce strict header validation
327  * checks and may prevent reading of files which could otherwise be
328  * processed.
329  */
330 #define EXR_CONTEXT_FLAG_STRICT_HEADER (1 << 0)
331 
332 /** @brief Disables error messages while parsing headers
333  *
334  * The return values will remain the same, but error reporting will be
335  * skipped. This is only valid for reading contexts
336  */
337 #define EXR_CONTEXT_FLAG_SILENT_HEADER_PARSE (1 << 1)
338 
339 /** @brief Disables reconstruction logic upon corrupt / missing data chunks
340  *
341  * This will disable the reconstruction logic that searches through an
342  * incomplete file, and will instead just return errors at read
343  * time. This is only valid for reading contexts
344  */
345 #define EXR_CONTEXT_FLAG_DISABLE_CHUNK_RECONSTRUCTION (1 << 2)
346 
347 /** @brief Writes an old-style, sorted header with minimal information */
348 #define EXR_CONTEXT_FLAG_WRITE_LEGACY_HEADER (1 << 3)
349 
350 /* clang-format off */
351 /** @brief Simple macro to initialize the context initializer with default values. */
352 #define EXR_DEFAULT_CONTEXT_INITIALIZER \
353  { sizeof (exr_context_initializer_t), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1.f, 0, { 0, 0, 0, 0 } }
354 /* clang-format on */
355 
356 /** @} */ /* context function pointer declarations */
357 
358 /** @brief Check the magic number of the file and report
359  * `EXR_ERR_SUCCESS` if the file appears to be a valid file (or at least
360  * has the correct magic number and can be read).
361  */
363  const char* filename, const exr_context_initializer_t* ctxtdata);
364 
365 /** @brief Close and free any internally allocated memory,
366  * calling any provided destroy function for custom streams.
367  *
368  * If the file was opened for write, first save the chunk offsets
369  * or any other unwritten data.
370  */
371 EXR_EXPORT exr_result_t exr_finish (exr_context_t* ctxt);
372 
373 /** @brief Create and initialize a read-only exr read context.
374  *
375  * If a custom read function is provided, the filename is for
376  * informational purposes only, the system assumes the user has
377  * previously opened a stream, file, or whatever and placed relevant
378  * data in userdata to access that.
379  *
380  * One notable attribute of the context is that once it has been
381  * created and returned a successful code, it has parsed all the
382  * header data. This is done as one step such that it is easier to
383  * provide a safe context for multiple threads to request data from
384  * the same context concurrently.
385  *
386  * Once finished reading data, use exr_finish() to clean up
387  * the context.
388  *
389  * If you have custom I/O requirements, see the initializer context
390  * documentation \ref exr_context_initializer_t. The @p ctxtdata parameter
391  * is optional, if `NULL`, default values will be used.
392  */
394  exr_context_t* ctxt,
395  const char* filename,
396  const exr_context_initializer_t* ctxtdata);
397 
398 /** @brief Enum describing how default files are handled during write. */
400 {
402  0, /**< Overwrite filename provided directly, deleted upon error. */
404  1 /**< Create a temporary file, renaming it upon successful write, leaving original upon error */
406 
407 /** @brief Create and initialize a write-only context.
408  *
409  * If a custom write function is provided, the filename is for
410  * informational purposes only, and the @p default_mode parameter will be
411  * ignored. As such, the system assumes the user has previously opened
412  * a stream, file, or whatever and placed relevant data in userdata to
413  * access that.
414  *
415  * Multi-Threading: To avoid issues with creating multi-part EXR
416  * files, the library approaches writing as a multi-step process, so
417  * the same concurrent guarantees can not be made for writing a
418  * file. The steps are:
419  *
420  * 1. Context creation (this function)
421  *
422  * 2. Part definition (required attributes and additional metadata)
423  *
424  * 3. Transition to writing data (this "commits" the part definitions,
425  * any changes requested after will result in an error)
426  *
427  * 4. Write part data in sequential order of parts (part<sub>0</sub>
428  * -> part<sub>N-1</sub>).
429  *
430  * 5. Within each part, multiple threads can be encoding and writing
431  * data concurrently. For some EXR part definitions, this may be able
432  * to write data concurrently when it can predict the chunk sizes, or
433  * data is allowed to be padded. For others, it may need to
434  * temporarily cache chunks until the data is received to flush in
435  * order. The concurrency around this is handled by the library
436  *
437  * 6. Once finished writing data, use exr_finish() to clean
438  * up the context, which will flush any unwritten data such as the
439  * final chunk offset tables, and handle the temporary file flags.
440  *
441  * If you have custom I/O requirements, see the initializer context
442  * documentation \ref exr_context_initializer_t. The @p ctxtdata
443  * parameter is optional, if `NULL`, default values will be used.
444  */
446  exr_context_t* ctxt,
447  const char* filename,
448  exr_default_write_mode_t default_mode,
449  const exr_context_initializer_t* ctxtdata);
450 
451 /** @brief Create a new context for updating an exr file in place.
452  *
453  * This is a custom mode that allows one to modify the value of a
454  * metadata entry, although not to change the size of the header, or
455  * any of the image data.
456  *
457  * If you have custom I/O requirements, see the initializer context
458  * documentation \ref exr_context_initializer_t. The @p ctxtdata parameter
459  * is optional, if `NULL`, default values will be used.
460  */
462  exr_context_t* ctxt,
463  const char* filename,
464  const exr_context_initializer_t* ctxtdata);
465 
466 /** @brief Retrieve the file name the context is for as provided
467  * during the start routine.
468  *
469  * Do not free the resulting string.
470  */
472 exr_get_file_name (exr_const_context_t ctxt, const char** name);
473 
474 /** @brief Query the user data the context was constructed with. This
475  * is perhaps useful in the error handler callback to jump back into
476  * an object the user controls.
477  */
479 exr_get_user_data (exr_const_context_t ctxt, void** userdata);
480 
481 /** Any opaque attribute data entry of the specified type is tagged
482  * with these functions enabling downstream users to unpack (or pack)
483  * the data.
484  *
485  * The library handles the memory packed data internally, but the
486  * handler is expected to allocate and manage memory for the
487  * *unpacked* buffer (the library will call the destroy function).
488  *
489  * NB: the pack function will be called twice (unless there is a
490  * memory failure), the first with a `NULL` buffer, requesting the
491  * maximum size (or exact size if known) for the packed buffer, then
492  * the second to fill the output packed buffer, at which point the
493  * size can be re-updated to have the final, precise size to put into
494  * the file.
495  */
497  exr_context_t ctxt,
498  const char* type,
499  exr_result_t (*unpack_func_ptr) (
500  exr_context_t ctxt,
501  const void* data,
502  int32_t attrsize,
503  int32_t* outsize,
504  void** outbuffer),
505  exr_result_t (*pack_func_ptr) (
506  exr_context_t ctxt,
507  const void* data,
508  int32_t datasize,
509  int32_t* outsize,
510  void* outbuffer),
511  void (*destroy_unpacked_func_ptr) (
512  exr_context_t ctxt, void* data, int32_t datasize));
513 
514 /** @brief Enable long name support in the output context */
516 exr_set_longname_support (exr_context_t ctxt, int onoff);
517 
518 /** @brief Write the header data.
519  *
520  * Opening a new output file has a small initialization state problem
521  * compared to opening for read/update: we need to enable the user
522  * to specify an arbitrary set of metadata across an arbitrary number
523  * of parts. To avoid having to create the list of parts and entire
524  * metadata up front, prior to calling the above exr_start_write(),
525  * allow the data to be set, then once this is called, it switches
526  * into a mode where the library assumes the data is now valid.
527  *
528  * It will recompute the number of chunks that will be written, and
529  * reset the chunk offsets. If you modify file attributes or part
530  * information after a call to this, it will error.
531  */
532 EXR_EXPORT exr_result_t exr_write_header (exr_context_t ctxt);
533 
534 /** @} */
535 
536 #ifdef __cplusplus
537 } /* extern "C" */
538 #endif
539 
540 #endif /* OPENEXR_CONTEXT_H */
EXR_EXPORT exr_result_t exr_start_write(exr_context_t *ctxt, const char *filename, exr_default_write_mode_t default_mode, const exr_context_initializer_t *ctxtdata)
Create and initialize a write-only context.
void(* exr_memory_free_func_t)(void *ptr)
Function pointer used to hold a free-like routine.
Definition: openexr_base.h:177
GT_API const UT_StringHolder filename
exr_query_size_func_ptr_t size_fn
Custom size query routine.
exr_default_write_mode
Enum describing how default files are handled during write.
Struct used to pass function pointers into the context initialization routines.
void
Definition: png.h:1083
size_t size
Size member to tag initializer for version stability.
int64_t(* exr_write_func_ptr_t)(exr_const_context_t ctxt, void *userdata, const void *buffer, uint64_t sz, uint64_t offset, exr_stream_error_func_ptr_t error_cb)
EXR_EXPORT exr_result_t exr_start_inplace_header_update(exr_context_t *ctxt, const char *filename, const exr_context_initializer_t *ctxtdata)
Create a new context for updating an exr file in place.
exr_error_handler_cb_t error_handler_fn
Error callback function pointer.
GLuint buffer
Definition: glcorearb.h:660
exr_destroy_stream_func_ptr_t destroy_fn
Optional function to destroy the user data block of a custom stream.
exr_read_func_ptr_t read_fn
Custom read routine.
const struct _priv_exr_context_t * exr_const_context_t
struct _exr_context_initializer_v3 exr_context_initializer_t
Struct used to pass function pointers into the context initialization routines.
exr_memory_free_func_t free_fn
int64_t(* exr_read_func_ptr_t)(exr_const_context_t ctxt, void *userdata, void *buffer, uint64_t sz, uint64_t offset, exr_stream_error_func_ptr_t error_cb)
Read custom function pointer.
GLintptr offset
Definition: glcorearb.h:665
exr_result_t(* exr_stream_error_func_ptr_t)(exr_const_context_t ctxt, exr_result_t code, const char *fmt,...) EXR_PRINTF_FUNC_ATTRIBUTE
Stream error notifier.
EXR_EXPORT exr_result_t exr_start_read(exr_context_t *ctxt, const char *filename, const exr_context_initializer_t *ctxtdata)
Create and initialize a read-only exr read context.
EXR_EXPORT exr_result_t exr_get_user_data(exr_const_context_t ctxt, void **userdata)
Query the user data the context was constructed with. This is perhaps useful in the error handler cal...
void(* exr_error_handler_cb_t)(exr_const_context_t ctxt, exr_result_t code, const char *msg)
Error callback function.
int32_t exr_result_t
#define EXR_EXPORT
struct _priv_exr_context_t * exr_context_t
EXR_EXPORT exr_result_t exr_get_file_name(exr_const_context_t ctxt, const char **name)
Retrieve the file name the context is for as provided during the start routine.
GLuint const GLchar * name
Definition: glcorearb.h:786
void(* exr_destroy_stream_func_ptr_t)(exr_const_context_t ctxt, void *userdata, int failed)
exr_memory_allocation_func_t alloc_fn
#define EXR_PRINTF_FUNC_ATTRIBUTE
EXR_EXPORT exr_result_t exr_finish(exr_context_t *ctxt)
Close and free any internally allocated memory, calling any provided destroy function for custom stre...
enum exr_default_write_mode exr_default_write_mode_t
Enum describing how default files are handled during write.
void *(* exr_memory_allocation_func_t)(size_t bytes)
Function pointer used to hold a malloc-like routine.
Definition: openexr_base.h:161
int64_t(* exr_query_size_func_ptr_t)(exr_const_context_t ctxt, void *userdata)
EXR_EXPORT exr_result_t exr_write_header(exr_context_t ctxt)
Write the header data.
EXR_EXPORT exr_result_t exr_test_file_header(const char *filename, const exr_context_initializer_t *ctxtdata)
Check the magic number of the file and report EXR_ERR_SUCCESS if the file appears to be a valid file ...
EXR_EXPORT exr_result_t exr_register_attr_type_handler(exr_context_t ctxt, const char *type, exr_result_t(*unpack_func_ptr)(exr_context_t ctxt, const void *data, int32_tattrsize, int32_t *outsize, void **outbuffer), exr_result_t(*pack_func_ptr)(exr_context_t ctxt, const void *data, int32_tdatasize, int32_t *outsize, void *outbuffer), void(*destroy_unpacked_func_ptr)(exr_context_t ctxt, void *data, int32_t datasize))
type
Definition: core.h:1059
EXR_EXPORT exr_result_t exr_set_longname_support(exr_context_t ctxt, int onoff)
Enable long name support in the output context.
Definition: format.h:895
exr_write_func_ptr_t write_fn
Custom write routine.