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  * TODO: This does not handle the ability to mmap a file and get to
130  * zero copy
131  */
132 typedef int64_t (*exr_read_func_ptr_t) (
133  exr_const_context_t ctxt,
134  void* userdata,
135  void* buffer,
136  uint64_t sz,
137  uint64_t offset,
138  exr_stream_error_func_ptr_t error_cb);
139 
140 /** Write custom function pointer
141  *
142  * Used to write data to a custom output. Expects similar semantics to
143  * pwrite or WriteFile with overlapped data under win32.
144  *
145  * It is required that this provides thread-safe concurrent access to
146  * the same file. While it is unlikely that multiple threads will
147  * be used to write data for compressed forms, it is possible.
148  *
149  * A file should be expected to be accessed in the following pattern:
150  * - upon open, the header and part information attributes is constructed.
151  *
152  * - when the write_header routine is called, the header becomes immutable
153  * and is written to the file. This computes the space to store the chunk
154  * offsets, but does not yet write the values.
155  *
156  * - Image chunks are written to the file, and appear in the order
157  * they are written, not in the ordering that is required by the
158  * chunk offset table (unless written in that order). This may vary
159  * slightly if the size of the chunks is not directly known and
160  * tight packing of data is necessary.
161  *
162  * - at file close, the chunk offset tables are written to the file.
163  */
164 typedef int64_t (*exr_write_func_ptr_t) (
165  exr_const_context_t ctxt,
166  void* userdata,
167  const void* buffer,
168  uint64_t sz,
169  uint64_t offset,
170  exr_stream_error_func_ptr_t error_cb);
171 
172 /** @brief Struct used to pass function pointers into the context
173  * initialization routines.
174  *
175  * This partly exists to avoid the chicken and egg issue around
176  * creating the storage needed for the context on systems which want
177  * to override the malloc/free routines.
178  *
179  * However, it also serves to make a tidier/simpler set of functions
180  * to create and start processing exr files.
181  *
182  * The size member is required for version portability.
183  *
184  * It can be initialized using \c EXR_DEFAULT_CONTEXT_INITIALIZER.
185  *
186  * \code{.c}
187  * exr_context_initializer_t myctxtinit = DEFAULT_CONTEXT_INITIALIZER;
188  * myctxtinit.error_cb = &my_super_cool_error_callback_function;
189  * ...
190  * \endcode
191  *
192  */
194 {
195  /** @brief Size member to tag initializer for version stability.
196  *
197  * This should be initialized to the size of the current
198  * structure. This allows EXR to add functions or other
199  * initializers in the future, and retain version compatibility
200  */
201  size_t size;
202 
203  /** @brief Error callback function pointer
204  *
205  * The error callback is allowed to be `NULL`, and will use a
206  * default print which outputs to \c stderr.
207  *
208  * @sa exr_error_handler_cb_t
209  */
211 
212  /** Custom allocator, if `NULL`, will use malloc. @sa exr_memory_allocation_func_t */
214 
215  /** Custom deallocator, if `NULL`, will use free. @sa exr_memory_free_func_t */
217 
218  /** Blind data passed to custom read, size, write, destroy
219  * functions below. Up to user to manage this pointer.
220  */
221  void* user_data;
222 
223  /** @brief Custom read routine.
224  *
225  * This is only used during read or update contexts. If this is
226  * provided, it is expected that the caller has previously made
227  * the stream available, and placed whatever stream/file data
228  * into \c user_data above.
229  *
230  * If this is `NULL`, and the context requested is for reading an
231  * exr file, an internal implementation is provided for reading
232  * from normal filesystem files, and the filename provided is
233  * attempted to be opened as such.
234  *
235  * Expected to be `NULL` for a write-only operation, but is ignored
236  * if it is provided.
237  *
238  * For update contexts, both read and write functions must be
239  * provided if either is.
240  *
241  * @sa exr_read_func_ptr_t
242  */
244 
245  /** @brief Custom size query routine.
246  *
247  * Used to provide validation when reading header values. If this
248  * is not provided, but a custom read routine is provided, this
249  * will disable some of the validation checks when parsing the
250  * image header.
251  *
252  * Expected to be `NULL` for a write-only operation, but is ignored
253  * if it is provided.
254  *
255  * @sa exr_query_size_func_ptr_t
256  */
258 
259  /** @brief Custom write routine.
260  *
261  * This is only used during write or update contexts. If this is
262  * provided, it is expected that the caller has previously made
263  * the stream available, and placed whatever stream/file data
264  * into \c user_data above.
265  *
266  * If this is `NULL`, and the context requested is for writing an
267  * exr file, an internal implementation is provided for reading
268  * from normal filesystem files, and the filename provided is
269  * attempted to be opened as such.
270  *
271  * For update contexts, both read and write functions must be
272  * provided if either is.
273  *
274  * @sa exr_write_func_ptr_t
275  */
277 
278  /** @brief Optional function to destroy the user data block of a custom stream.
279  *
280  * Allows one to free any user allocated data, and close any handles.
281  *
282  * @sa exr_destroy_stream_func_ptr_t
283  * */
285 
286  /** Initialize a field specifying what the maximum image width
287  * allowed by the context is. See exr_set_default_maximum_image_size() to
288  * understand how this interacts with global defaults.
289  */
291 
292  /** Initialize a field specifying what the maximum image height
293  * allowed by the context is. See exr_set_default_maximum_image_size() to
294  * understand how this interacts with global defaults.
295  */
297 
298  /** Initialize a field specifying what the maximum tile width
299  * allowed by the context is. See exr_set_default_maximum_tile_size() to
300  * understand how this interacts with global defaults.
301  */
303 
304  /** Initialize a field specifying what the maximum tile height
305  * allowed by the context is. See exr_set_default_maximum_tile_size() to
306  * understand how this interacts with global defaults.
307  */
309 
310  /** Initialize a field specifying what the default zip compression level should be
311  * for this context. See exr_set_default_zip_compresion_level() to
312  * set it for all contexts.
313  */
315 
316  /** Initialize the default dwa compression quality. See
317  * exr_set_default_dwa_compression_quality() to set the default
318  * for all contexts.
319  */
320  float dwa_quality;
321 
322  /** Initialize with a bitwise or of the various context flags
323  */
324  int flags;
325 
326  uint8_t pad[4];
328 
329 /** @brief context flag which will enforce strict header validation
330  * checks and may prevent reading of files which could otherwise be
331  * processed.
332  */
333 #define EXR_CONTEXT_FLAG_STRICT_HEADER (1 << 0)
334 
335 /** @brief Disables error messages while parsing headers
336  *
337  * The return values will remain the same, but error reporting will be
338  * skipped. This is only valid for reading contexts
339  */
340 #define EXR_CONTEXT_FLAG_SILENT_HEADER_PARSE (1 << 1)
341 
342 /** @brief Disables reconstruction logic upon corrupt / missing data chunks
343  *
344  * This will disable the reconstruction logic that searches through an
345  * incomplete file, and will instead just return errors at read
346  * time. This is only valid for reading contexts
347  */
348 #define EXR_CONTEXT_FLAG_DISABLE_CHUNK_RECONSTRUCTION (1 << 2)
349 
350 /** @brief Writes an old-style, sorted header with minimal information */
351 #define EXR_CONTEXT_FLAG_WRITE_LEGACY_HEADER (1 << 3)
352 
353 /* clang-format off */
354 /** @brief Simple macro to initialize the context initializer with default values. */
355 #define EXR_DEFAULT_CONTEXT_INITIALIZER \
356  { 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 } }
357 /* clang-format on */
358 
359 /** @} */ /* context function pointer declarations */
360 
361 /** @brief Check the magic number of the file and report
362  * `EXR_ERR_SUCCESS` if the file appears to be a valid file (or at least
363  * has the correct magic number and can be read).
364  */
366  const char* filename, const exr_context_initializer_t* ctxtdata);
367 
368 /** @brief Close and free any internally allocated memory,
369  * calling any provided destroy function for custom streams.
370  *
371  * If the file was opened for write, first save the chunk offsets
372  * or any other unwritten data.
373  */
374 EXR_EXPORT exr_result_t exr_finish (exr_context_t* ctxt);
375 
376 /** @brief Create and initialize a read-only exr read context.
377  *
378  * If a custom read function is provided, the filename is for
379  * informational purposes only, the system assumes the user has
380  * previously opened a stream, file, or whatever and placed relevant
381  * data in userdata to access that.
382  *
383  * One notable attribute of the context is that once it has been
384  * created and returned a successful code, it has parsed all the
385  * header data. This is done as one step such that it is easier to
386  * provide a safe context for multiple threads to request data from
387  * the same context concurrently.
388  *
389  * Once finished reading data, use exr_finish() to clean up
390  * the context.
391  *
392  * If you have custom I/O requirements, see the initializer context
393  * documentation \ref exr_context_initializer_t. The @p ctxtdata parameter
394  * is optional, if `NULL`, default values will be used.
395  */
397  exr_context_t* ctxt,
398  const char* filename,
399  const exr_context_initializer_t* ctxtdata);
400 
401 /** @brief Enum describing how default files are handled during write. */
403 {
405  0, /**< Overwrite filename provided directly, deleted upon error. */
407  1 /**< Create a temporary file, renaming it upon successful write, leaving original upon error */
409 
410 /** @brief Create and initialize a write-only context.
411  *
412  * If a custom write function is provided, the filename is for
413  * informational purposes only, and the @p default_mode parameter will be
414  * ignored. As such, the system assumes the user has previously opened
415  * a stream, file, or whatever and placed relevant data in userdata to
416  * access that.
417  *
418  * Multi-Threading: To avoid issues with creating multi-part EXR
419  * files, the library approaches writing as a multi-step process, so
420  * the same concurrent guarantees can not be made for writing a
421  * file. The steps are:
422  *
423  * 1. Context creation (this function)
424  *
425  * 2. Part definition (required attributes and additional metadata)
426  *
427  * 3. Transition to writing data (this "commits" the part definitions,
428  * any changes requested after will result in an error)
429  *
430  * 4. Write part data in sequential order of parts (part<sub>0</sub>
431  * -> part<sub>N-1</sub>).
432  *
433  * 5. Within each part, multiple threads can be encoding and writing
434  * data concurrently. For some EXR part definitions, this may be able
435  * to write data concurrently when it can predict the chunk sizes, or
436  * data is allowed to be padded. For others, it may need to
437  * temporarily cache chunks until the data is received to flush in
438  * order. The concurrency around this is handled by the library
439  *
440  * 6. Once finished writing data, use exr_finish() to clean
441  * up the context, which will flush any unwritten data such as the
442  * final chunk offset tables, and handle the temporary file flags.
443  *
444  * If you have custom I/O requirements, see the initializer context
445  * documentation \ref exr_context_initializer_t. The @p ctxtdata
446  * parameter is optional, if `NULL`, default values will be used.
447  */
449  exr_context_t* ctxt,
450  const char* filename,
451  exr_default_write_mode_t default_mode,
452  const exr_context_initializer_t* ctxtdata);
453 
454 /** @brief Create a new context for updating an exr file in place.
455  *
456  * This is a custom mode that allows one to modify the value of a
457  * metadata entry, although not to change the size of the header, or
458  * any of the image data.
459  *
460  * If you have custom I/O requirements, see the initializer context
461  * documentation \ref exr_context_initializer_t. The @p ctxtdata parameter
462  * is optional, if `NULL`, default values will be used.
463  */
465  exr_context_t* ctxt,
466  const char* filename,
467  const exr_context_initializer_t* ctxtdata);
468 
469 /** @brief Create a new context for temporary use in memory.
470  *
471  * This is a custom mode that does not supporting writing actual image
472  * data, but one can create one of these, manipulate attributes,
473  * define additional parts, run validation, etc. without any
474  * requirement of actual file i/o.
475  *
476  * Note that this creates an defines an initial part for use, so one
477  * can immediately start definining attributes into part index 0.
478  *
479  * See the initializer context documentation \ref
480  * exr_context_initializer_t to be able to provide allocation
481  * overrides or other controls. The @p ctxtdata parameter is optional,
482  * if `NULL`, default values will be used.
483  */
485  exr_context_t* ctxt,
486  const char* context_name,
487  const exr_context_initializer_t* ctxtdata);
488 
489 /** @brief Retrieve the file name the context is for as provided
490  * during the start routine.
491  *
492  * Do not free the resulting string.
493  */
495 exr_get_file_name (exr_const_context_t ctxt, const char** name);
496 
497 /** @brief Retrieve the file version and flags the context is for as
498  * parsed during the start routine.
499  */
501 exr_get_file_version_and_flags (exr_const_context_t ctxt, uint32_t* ver);
502 
503 /** @brief Query the user data the context was constructed with. This
504  * is perhaps useful in the error handler callback to jump back into
505  * an object the user controls.
506  */
508 exr_get_user_data (exr_const_context_t ctxt, void** userdata);
509 
510 /** Any opaque attribute data entry of the specified type is tagged
511  * with these functions enabling downstream users to unpack (or pack)
512  * the data.
513  *
514  * The library handles the memory packed data internally, but the
515  * handler is expected to allocate and manage memory for the
516  * *unpacked* buffer (the library will call the destroy function).
517  *
518  * NB: the pack function will be called twice (unless there is a
519  * memory failure), the first with a `NULL` buffer, requesting the
520  * maximum size (or exact size if known) for the packed buffer, then
521  * the second to fill the output packed buffer, at which point the
522  * size can be re-updated to have the final, precise size to put into
523  * the file.
524  */
526  exr_context_t ctxt,
527  const char* type,
528  exr_result_t (*unpack_func_ptr) (
529  exr_context_t ctxt,
530  const void* data,
531  int32_t attrsize,
532  int32_t* outsize,
533  void** outbuffer),
534  exr_result_t (*pack_func_ptr) (
535  exr_context_t ctxt,
536  const void* data,
537  int32_t datasize,
538  int32_t* outsize,
539  void* outbuffer),
540  void (*destroy_unpacked_func_ptr) (
541  exr_context_t ctxt, void* data, int32_t datasize));
542 
543 /** @brief Enable long name support in the output context */
545 exr_set_longname_support (exr_context_t ctxt, int onoff);
546 
547 /** @brief Write the header data.
548  *
549  * Opening a new output file has a small initialization state problem
550  * compared to opening for read/update: we need to enable the user
551  * to specify an arbitrary set of metadata across an arbitrary number
552  * of parts. To avoid having to create the list of parts and entire
553  * metadata up front, prior to calling the above exr_start_write(),
554  * allow the data to be set, then once this is called, it switches
555  * into a mode where the library assumes the data is now valid.
556  *
557  * It will recompute the number of chunks that will be written, and
558  * reset the chunk offsets. If you modify file attributes or part
559  * information after a call to this, it will error.
560  */
561 EXR_EXPORT exr_result_t exr_write_header (exr_context_t ctxt);
562 
563 /** @} */
564 
565 #ifdef __cplusplus
566 } /* extern "C" */
567 #endif
568 
569 #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_EXPORT exr_result_t exr_start_temporary_context(exr_context_t *ctxt, const char *context_name, const exr_context_initializer_t *ctxtdata)
Create a new context for temporary use in memory.
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.
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
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))
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:1821
EXR_EXPORT exr_result_t exr_get_file_version_and_flags(exr_const_context_t ctxt, uint32_t *ver)
Retrieve the file version and flags the context is for as parsed during the start routine...
exr_write_func_ptr_t write_fn
Custom write routine.