Reading and Writing OpenEXR Image Files with the C-language API¶
The OpenEXRCore library has a few notable features to consider prior to beginning use:
- stateless
The library is largely state-free, enabling multiple plugins or just different areas within the same process to customize the errors being reported (i.e. swallow them, report them differently, etc.), provide custom memory allocation routines, or replace the file I/O routines with their own. To do this, every file is called a “context”, and each context can be initialized with a customized set of routines or values. There are global defaults for all of this behavior, but they are just that: defaults.
- result codes
Every routine returns a result code (success or an error code). Besides some low level routines where a good error message is not possible, the rest of the library attempts to provide a meaningful message as to what is going wrong via a formatted message. This rule of every function returning a result code means that in some scenarios, the code may be slightly more verbose, but it should be a safer library in the long run.
The C api is designed around the fundamental units:
Header and attributes
Multiple parts (optional)
Chunks of image or deep data
Transformations of those chunks into the requested form
All requests to read or write image or data from a file must happen in “chunk” requests. There are API differences depending on whether the OpenEXR part being read contains scanline data or tiled data, and to handle deep vs shallow image files. However, largely all the same functions are used to read and write this atomic data.
Simple Example¶
To get started, here is a simple code snippet that starts to read a file:
1 exr_context_initializer_t ctxtinit = EXR_DEFAULT_CONTEXT_INITIALIZER;
2 exr_context_t myfile;
3 exr_result_t rv = exr_start_read(&myfile, “/tmp/foo.exr”, &ctxtinit);
4 if (rv != EXR_ERR_SUCCESS)
5 {
6 /* do something about the error */
7 }
Reading and Writing¶
This will open a file and parse the header. One can immediately notice
this context initializer structure. This provides a path to specify
custom handlers for I/O, memory, error reporting, etc. Writing is a
near mirror, just using exr_start_write(), with the additional option
about whether to handle creation of a temporary file and rename it, or
to write directly. In both cases, along with the path to quick edit
attributes in place, the context is closed / destroyed with a call to
exr_finish.
For reading image data, once the file is opened using this
exr_start_read() call, the remaining calls are all thread-safe and
as lock free as possible.
Assuming the parsing of the header and opening of the file are
successful, the remaining API then takes both this context that is
initialized as well as a part index. In this way, the C library
provides transparent, integrated multi-part OpenEXR support, and does
not further differentiate between the variants. One can query how many
parts are in the file via exr_get_count(). Furthermore, there are
a wealth of routines provided to access the attributes (metadata)
contained within the file. These will not be described here beyond
where necessary.
There is a set of functions to query (or set while writing) the information for a particular part index. They are too numerous to list here, but there are functions to query the required attributes of the file, and then more generic type-specific functions to access attributes by type. Further, the attributes can be accessed either in a sorted order, or the order within which they appear in the file. One example might be to retrieve the data window:
exr_attr_box2i_t datawindow;
exr_result_t rv = exr_get_data_window(ctxt, 0, &datawindow);
Data Types¶
Notice that this example does not use the traditional Imath types
here. The Imath types C++ objects with a rich set of functions, but
are not viable in a C api. The types for the C layer are only provided
to transport the data, and not to operate on the data. But with the
new type conversion constructors present in version 3.1 of Imath,
types such as the vector types (i.e. exr_attr_v3f_t) should
transparently convert to their respective Imath type.
Chunks¶
Once the calling program has created the context, inspected the header
data to decide the next course of action, and started to operate on a
file, one must operate in chunk units. For a scanline-based file, this
means requesting scanlines in groups of scanlines contained in one
chunk. The routine exr_get_scanlines_per_chunk() returns this
count. This is currently 1, 16, or 32. For tiled files, the base unit
of I/O is a tile itself: the chunk is a tile. One can use the routines
exr_get_tile_descriptor(), exr_get_tile_levels(), and
exr_get_tile_sizes() as utilities to introspect tile information.
In order to read data, use exr_read_scanline_block_info() or
exr_read_tile_block_info() to initialize a structure with the data
to read one of these chunks of data. Then there are the corresponding
exr_read_chunk(), exr_read_deep_chunk() which read the
data. Analogously, there are write versions of these functions.
Encode and Decode¶
The above is very simple, but only provides the raw, compressed and packed data. These are preferred if you are writing a utility to copy, combine, or split out parts of EXR files and just want the raw data blocks. However, to actually use the data in an application, the encoding and decoding pipeline methods should be used. These provide and combine the read step above, such that they are free to optimize the data path when the data is uncompressed.
The decoding pipeline consists of a structure that contains relevant channel and data type information, in addition to allocation routines, function pointers to specialize the stages of the pipeline, and pointers to memory buffers to use. This enables the calling application to re-use decode pipeline buffers (where it can determine thread safety), and avoid constant memory allocation / deallocation while performing such tasks as reading scanlines of an image into one large buffer. The decode pipeline consists of 3 (4 when reading deep) simple steps:
Read the data
De-compress the data (if it is compressed)
Optionally update allocation based on sample data read (deep only)
Unpack the data (re-orient from the on-disk representation)
These decoding pipelines (or the mirror for encoding) provide the
caller with the ability to use the in-built routines for portions of
these steps (exr_decoding_choose_default_routines()), but then
customize the stages that make the most sense. So, for simplicity, one
could imagine implementing a GPU decoder to use the provided routines
for reading and decompressing, but then instead of interleaving the
data on the CPU, instead provide a custom routine to do that step on
the GPU by overriding the function pointer on the decoding structure.
Once you have decoded or encoded all the chunks required, it is
expected you will call exr_decoding_destroy() which will clean up
all the buffers associated with that instance of the decoding
pipeline. If you will be reading an entire image at once, it is
recommended to initialize the decoding pipeline once Regardless of
using the raw chunk API, or the richer decoding pipeline, both paths
start with a call to query information about the chunk to read, using
either exr_read_scanline_block_info() or
exr_ead_tile_block_info(). This fills in and initializes a
structure with information for that chunk, including how many bits
would result from unpacking that chunk, and it’s raw position on disk.
Reference¶
Basic Enumerated Types¶
-
enum exr_compression_t¶
enum declaring allowed values for uint8_t value stored in built-in compression type
Values:
-
enumerator EXR_COMPRESSION_NONE¶
-
enumerator EXR_COMPRESSION_RLE¶
-
enumerator EXR_COMPRESSION_ZIPS¶
-
enumerator EXR_COMPRESSION_ZIP¶
-
enumerator EXR_COMPRESSION_PIZ¶
-
enumerator EXR_COMPRESSION_PXR24¶
-
enumerator EXR_COMPRESSION_B44¶
-
enumerator EXR_COMPRESSION_B44A¶
-
enumerator EXR_COMPRESSION_DWAA¶
-
enumerator EXR_COMPRESSION_DWAB¶
-
enumerator EXR_COMPRESSION_LAST_TYPE¶
invalid value, provided for range checking
-
enumerator EXR_COMPRESSION_NONE¶
-
enum exr_envmap_t¶
enum declaring allowed values for uint8_t value stored in built-in env map type
Values:
-
enumerator EXR_ENVMAP_LATLONG¶
-
enumerator EXR_ENVMAP_CUBE¶
-
enumerator EXR_ENVMAP_LAST_TYPE¶
invalid value, provided for range checking
-
enumerator EXR_ENVMAP_LATLONG¶
-
enum exr_lineorder_t¶
enum declaring allowed values for uint8_t value stored in lineOrder type
Values:
-
enumerator EXR_LINEORDER_INCREASING_Y¶
-
enumerator EXR_LINEORDER_DECREASING_Y¶
-
enumerator EXR_LINEORDER_RANDOM_Y¶
-
enumerator EXR_LINEORDER_LAST_TYPE¶
invalid value, provided for range checking
-
enumerator EXR_LINEORDER_INCREASING_Y¶
-
enum exr_storage_t¶
enum declaring allowed values for part type
Values:
-
enumerator EXR_STORAGE_SCANLINE¶
corresponds to type of ‘scanlineimage’
-
enumerator EXR_STORAGE_TILED¶
corresponds to type of ‘tiledimage’
-
enumerator EXR_STORAGE_DEEP_SCANLINE¶
corresponds to type of ‘deepscanline’
-
enumerator EXR_STORAGE_DEEP_TILED¶
corresponds to type of ‘deeptile’
-
enumerator EXR_STORAGE_LAST_TYPE¶
invalid value, provided for range checking
-
enumerator EXR_STORAGE_SCANLINE¶
-
enum exr_tile_level_mode_t¶
Enum representing what type of tile information is contained.
Values:
-
enumerator EXR_TILE_ONE_LEVEL¶
single level of image data
-
enumerator EXR_TILE_MIPMAP_LEVELS¶
mipmapped image data
-
enumerator EXR_TILE_RIPMAP_LEVELS¶
ripmapped image data
-
enumerator EXR_TILE_LAST_TYPE¶
guard / out of range type
-
enumerator EXR_TILE_ONE_LEVEL¶
-
enum exr_tile_round_mode_t¶
Enum representing how to scale positions between levels.
Values:
-
enumerator EXR_TILE_ROUND_DOWN¶
-
enumerator EXR_TILE_ROUND_UP¶
-
enumerator EXR_TILE_ROUND_LAST_TYPE¶
-
enumerator EXR_TILE_ROUND_DOWN¶
-
enum exr_pixel_type_t¶
Enum capturing the underlying data type on a channel.
Values:
-
enumerator EXR_PIXEL_UINT¶
-
enumerator EXR_PIXEL_HALF¶
-
enumerator EXR_PIXEL_FLOAT¶
-
enumerator EXR_PIXEL_LAST_TYPE¶
-
enumerator EXR_PIXEL_UINT¶
-
enum exr_attr_list_access_mode¶
Values:
-
enumerator EXR_ATTR_LIST_FILE_ORDER¶
order they appear in the file
-
enumerator EXR_ATTR_LIST_SORTED_ORDER¶
alphabetically sorted
-
enumerator EXR_ATTR_LIST_FILE_ORDER¶
-
enum exr_perceptual_treatment_t¶
Hint for lossy compression methods about how to treat values (logarithmic or linear), meaning a human sees values like R, G, B, luminance difference between 0.1 and 0.2 as about the same as 1.0 to 2.0 (logarithmic), where chroma coordinates are closer to linear (0.1 and 0.2 is about the same difference as 1.0 and 1.1)
Values:
-
enumerator EXR_PERCEPTUALLY_LOGARITHMIC¶
-
enumerator EXR_PERCEPTUALLY_LINEAR¶
-
enumerator EXR_PERCEPTUALLY_LOGARITHMIC¶
-
enum exr_default_write_mode¶
enum describing how default files are handled during write
Values:
-
enumerator EXR_WRITE_FILE_DIRECTLY¶
overwrites filename provided directly, deleted upon error
-
enumerator EXR_INTERMEDIATE_TEMP_FILE¶
creates a temporary file, renaming it upon successful write, leaving original upon error
-
enumerator EXR_WRITE_FILE_DIRECTLY¶
Global State¶
-
void exr_get_library_version(int *maj, int *min, int *patch, const char **extra)¶
Retrieve the current library version.
The
extrastring is for custom installs, and is a static string, do not free the returned pointer
-
void exr_set_default_maximum_image_size(int w, int h)¶
Limit the size of image allowed to be parsed or created by the library.
This is used as a safety check against corrupt files, but can also serve to avoid potential issues on machines which have very constrained RAM
These values are among the only globals in the core layer of OpenEXR. The intended use is for applications to define a global default, which will be combined with the values provided to the individual context creation routine. The values are used to check against parsed header values. This adds some level of safety from memory overruns where a corrupt file given to the system may cause a large allocation to happen, enabling buffer overruns or other potential security issue.
These global values are combined with the values in exr_context_initializer_t using the following rules:
negative values are ignored.
if either value has a positive (non-zero) value, and the other has 0, the positive value is preferred.
If both are positive (non-zero), the minimum value is used.
If both values are 0, this disables the constrained size checks.
This function does not fail.
-
void exr_get_default_maximum_image_size(int *w, int *h)¶
Retrieve the global default maximum image size.
This function does not fail.
-
void exr_set_default_maximum_tile_size(int w, int h)¶
Limit the size of an image tile allowed to be parsed or created by the library.
Similar to image size, this places constraints on the maximum tile size as a safety check against bad file data
This is used as a safety check against corrupt files, but can also serve to avoid potential issues on machines which have very constrained RAM
These values are among the only globals in the core layer of OpenEXR. The intended use is for applications to define a global default, which will be combined with the values provided to the individual context creation routine. The values are used to check against parsed header values. This adds some level of safety from memory overruns where a corrupt file given to the system may cause a large allocation to happen, enabling buffer overruns or other potential security issue.
These global values are combined with the values in exr_context_initializer_t using the following rules:
negative values are ignored.
if either value has a positive (non-zero) value, and the other has 0, the positive value is preferred.
If both are positive (non-zero), the minimum value is used.
If both values are 0, this disables the constrained size checks.
This function does not fail.
-
void exr_get_default_maximum_tile_size(int *w, int *h)¶
Retrieve the global maximum tile size.
This function does not fail.
-
void exr_set_default_memory_routines(exr_memory_allocation_func_t alloc_func, exr_memory_free_func_t free_func)¶
Allows the user to override default allocator used internal allocations necessary for files, attributes, and other temporary memory.
These routines may be overridden when creating a specific context, however this provides global defaults such that the default can be applied.
If either pointer is 0, the appropriate malloc/free routine will be substituted.
This function does not fail.
Chunk Reading¶
-
exr_result_t exr_read_scanline_chunk_info(exr_const_context_t ctxt, int part_index, int y, exr_chunk_info_t *cinfo)¶
-
exr_result_t exr_read_tile_chunk_info(exr_const_context_t ctxt, int part_index, int tilex, int tiley, int levelx, int levely, exr_chunk_info_t *cinfo)¶
-
exr_result_t exr_read_chunk(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, void *packed_data)¶
Read the packed data block for a chunk.
This assumes that the buffer pointed to by
packed_datais large enough to hold the chunk block info packed_size bytes
-
exr_result_t exr_read_deep_chunk(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, void *packed_data, void *sample_data)¶
Read chunk for deep data.
This allows one to read the packed data, the sample count data, or both. exr_read_chunk also works to read deep data packed data, but this is a routine to get the sample count table and the packed data in one go, or if you want to pre-read the sample count data, you can get just that buffer.
Chunks¶
-
struct exr_chunk_info_t¶
Structure describing raw data information about a chunk.
A chunk is the generic term for a pixel data block in an EXR file, as described in the OpenEXR File Layout documentation. This is common between all different forms of data that can be stored.
Chunk Writing¶
-
exr_result_t exr_write_scanline_chunk_info(exr_context_t ctxt, int part_index, int y, exr_chunk_info_t *cinfo)¶
Initialize a exr_chunk_info_t structure when encoding scanline data (similar to read but does not do anything with a chunk table)
-
exr_result_t exr_write_tile_chunk_info(exr_context_t ctxt, int part_index, int tilex, int tiley, int levelx, int levely, exr_chunk_info_t *cinfo)¶
Initialize a chunk_info_t structure when encoding tiled data (similar to read but does not do anything with a chunk table)
-
exr_result_t exr_write_scanline_chunk(exr_context_t ctxt, int part_index, int y, const void *packed_data, uint64_t packed_size)¶
ymust the appropriate starting y for the specified chunk
-
exr_result_t exr_write_deep_scanline_chunk(exr_context_t ctxt, int part_index, int y, const void *packed_data, uint64_t packed_size, uint64_t unpacked_size, const void *sample_data, uint64_t sample_data_size)¶
ymust the appropriate starting y for the specified chunk
-
exr_result_t exr_write_tile_chunk(exr_context_t ctxt, int part_index, int tilex, int tiley, int levelx, int levely, const void *packed_data, uint64_t packed_size)¶
-
exr_result_t exr_write_deep_tile_chunk(exr_context_t ctxt, int part_index, int tilex, int tiley, int levelx, int levely, const void *packed_data, uint64_t packed_size, uint64_t unpacked_size, const void *sample_data, uint64_t sample_data_size)¶
Open for Read¶
-
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_SUCCESSif the file appears to be a valid file (or at least has the correct magic number and can be read)
-
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.
If a custom read function is provided, the filename is for informational purposes only, the system assumes the user has previously opened a stream, file, or whatever and placed relevant data in userdata to access that.
One notable attribute of the context is that once it has been created and returned a successful code, it has parsed all the header data. This is done as one step such that it is easier to provide a safe context for multiple threads to request data from the same context concurrently.
Once finished reading data, use exr_finish to clean up the context.
If you have custom I/O requirements, see the initializer context documentation exr_context_initializer_t. The
ctxtdataparameter is optional, ifNULL, default values will be used.
Open for Write¶
-
exr_result_t exr_start_write(exr_context_t *ctxt, const char *filename, enum exr_default_write_mode default_mode, const exr_context_initializer_t *ctxtdata)¶
Creates and initializes a write-only context.
If a custom write function is provided, the filename is for informational purposes only, and the
default_modeparameter will be ignored. As such, the system assumes the user has previously opened a stream, file, or whatever and placed relevant data in userdata to access that.Multi-Threading: To avoid issues with creating multi-part EXR files, the library approaches writing as a multi-step process, so the same concurrent guarantees can not be made for writing a file. The steps are:
Context creation (this function)
Part definition (required attributes and additional metadata)
Transition to writing data (this “commits” the part definitions, any changes requested after will result in an error)
Write part data in sequential order of parts ( part 0->(N-1) ).
Within each part, multiple threads can be encoding and writing data concurrently. For some EXR part definitions, this may be able to write data concurrently when it can predict the chunk sizes, or data is allowed to be padded. For others, it may need to temporarily cache chunks until the data is received to flush in order. The concurrency around this is handled by the library
Once finished writing data, use exr_finish to clean up the context, which will flush any unwritten data such as the final chunk offset tables, and handle the temporary file flags.
If you have custom I/O requirements, see the initializer context documentation exr_context_initializer_t. The
ctxtdataparameter is optional, if NULL, default values will be used.
-
exr_result_t exr_start_inplace_header_update(exr_context_t *ctxt, const char *filename, const exr_context_initializer_t *ctxtdata)¶
Creates a new context for updating an exr file in place.
This is a custom mode that allows one to modify the value of a metadata entry, although not to change the size of the header, or any of the image data.
If you have custom I/O requirements, see the initializer context documentation exr_context_initializer_t. The
ctxtdataparameter is optional, if NULL, default values will be used.
-
exr_result_t exr_write_header(exr_context_t ctxt)¶
Write the header data.
Opening a new output file has a small initialization state problem compared to opening for read / update: we need to enable the user to specify an arbitrary set of metadata across an arbitrary number of parts. To avoid having to create the list of parts and entire metadata up front, prior to calling the above exr_start_write, allow the data to be set, then once this is called, it switches into a mode where the library assumes the data is now valid.
It will recompute the number of chunks that will be written, and reset the chunk offsets. If you modify file attributes or part information after a call to this, it will error.
-
exr_result_t exr_set_longname_support(exr_context_t ctxt, int onoff)¶
Enable long name support in the output context.
Close¶
-
exr_result_t exr_finish(exr_context_t *ctxt)¶
Close and free any internally allocated memory, calling any provided destroy function for custom streams.
If the file was opened for write, first save the chunk offsets or any other unwritten data.
Context¶
-
struct _exr_context_initializer¶
struct used to pass function pointers into the context initialization routines.
This partly exists to avoid the chicken and egg issue around creating the storage needed for the context on systems which want to override the malloc / free routines.
However, it also serves to make a tidier / simpler set of functions to create and start processing exr files.
The size member is required for version portability
It can be initialized using EXR_DEFAULT_CONTEXT_INITIALIZER
exr_context_initializer_t myctxtinit = DEFAULT_CONTEXT_INITIALIZER; myctxtinit.error_cb = &my_super_cool_error_callback_function; ...
Public Members
-
size_t size¶
size member to tag initializer for version stability.
This should be initialized to the size of the current structure. This allows EXR to add functions or other initializers in the future, and retain version compatibility
-
exr_error_handler_cb_t error_handler_fn¶
Error callback function pointer.
The error callback is allowed to be null, and will use a default print which outputs to stderr
- See
exr_error_handler_cb_t
-
exr_memory_allocation_func_t alloc_fn¶
custom allocator, if null, will use malloc.
- See
exr_memory_allocation_func_t
-
exr_memory_free_func_t free_fn¶
custom deallocator, if null, will use free.
- See
exr_memory_free_func_t
-
void *user_data¶
passed to custom read, size, write, destroy functions below.
Up to user to manage this pointer
-
exr_read_func_ptr_t read_fn¶
custom read routine.
This is only used during read or update contexts. If this is provided, it is expected that the caller has previously made the stream available, and placed whatever stream / file data into user_data above.
If this is NULL, and the context requested is for reading an exr file, an internal implementation is provided for reading from normal filesystem files, and the filename provided is attempted to be opened as such.
Expected to be NULL for a write-only operation, but is ignored if it is provided.
For update contexts, both read and write functions must be provided if either is.
- See
exr_read_func_ptr_t
-
exr_query_size_func_ptr_t size_fn¶
custom size query routine.
Used to provide validation when reading header values. If this is not provided, but a custom read routine is provided, this will disable some of the validation checks when parsing the image header.
Expected to be NULL for a write-only operation, but is ignored if it is provided.
- See
exr_query_size_func_ptr_t
-
exr_write_func_ptr_t write_fn¶
custom write routine.
This is only used during write or update contexts. If this is provided, it is expected that the caller has previously made the stream available, and placed whatever stream / file data into user_data above.
If this is NULL, and the context requested is for writing an exr file, an internal implementation is provided for reading from normal filesystem files, and the filename provided is attempted to be opened as such.
For update contexts, both read and write functions must be provided if either is.
- See
exr_write_func_ptr_t
-
exr_destroy_stream_func_ptr_t destroy_fn¶
optional function to destroy the user data block of a custom stream
Allows one to free any user allocated data, and close any handles.
- See
exr_destroy_stream_func_ptr_t
-
int max_image_width¶
initializes a field specifying what the maximum image width allowed by the context is.
See exr_set_default_maximum_image_size to understand how this interacts with global defaults
-
int max_image_height¶
initializes a field specifying what the maximum image height allowed by the context is.
See exr_set_default_maximum_image_size to understand how this interacts with global defaults
-
int max_tile_width¶
initializes a field specifying what the maximum tile width allowed by the context is.
See exr_set_default_maximum_tile_size to understand how this interacts with global defaults
-
int max_tile_height¶
initializes a field specifying what the maximum tile height allowed by the context is.
See exr_set_default_maximum_tile_size to understand how this interacts with global defaults
-
size_t size¶
-
typedef struct _exr_context_initializer exr_context_initializer_t¶
struct used to pass function pointers into the context initialization routines.
This partly exists to avoid the chicken and egg issue around creating the storage needed for the context on systems which want to override the malloc / free routines.
However, it also serves to make a tidier / simpler set of functions to create and start processing exr files.
The size member is required for version portability
It can be initialized using EXR_DEFAULT_CONTEXT_INITIALIZER
exr_context_initializer_t myctxtinit = DEFAULT_CONTEXT_INITIALIZER; myctxtinit.error_cb = &my_super_cool_error_callback_function; ...
-
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.
Do not free the resulting string.
-
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 callback to jump back into an object the user controls.
-
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_t attrsize, int32_t *outsize, void **outbuffer), exr_result_t (*pack_func_ptr)(exr_context_t ctxt, const void *data, int32_t datasize, int32_t *outsize, void *outbuffer), void (*destroy_unpacked_func_ptr)(exr_context_t ctxt, void *data, int32_t datasize))¶
Any opaque attribute data entry of the specified type is tagged with these functions enabling downstream users to unpack (or pack) the data.
The library handles the memory packed data internally, but the handler is expected to allocate and manage memory for the unpacked buffer (the library will call the destroy function).
NB: the pack function will be called twice (unless there is a memory failure), the first with a NULL buffer, requesting the maximum size (or exact size if known) for the packed buffer, then the second to fill the output packed buffer, at which point the size can be re-updated to have the final, precise size to put into the file.
Decoding¶
-
struct _exr_decode_pipeline¶
Structure meant to be used on a per-thread basis for reading exr data.
As should be obvious, this structure is NOT thread safe, but rather meant to be used by separate threads, which can all be accessing the same context concurrently.
Public Members
-
exr_coding_channel_info_t *channels¶
the output channel information for this chunk
User is expected to fill the channel pointers for the desired output channels (any that are NULL will be skipped) if you are going to use exr_choose_unpack_routine. If all that is desired is to read and decompress the data, this can be left uninitialized.
Describes the channel information. This information is allocated dynamically during exr_initialize_decoding
-
uint16_t decode_flags¶
Decode flags to control the behavior.
-
int part_index¶
copy of the parameters given to the initialize / update for convenience
-
void *decoding_user_data¶
can be used by the user to pass custom context data through the decode pipeline
-
void *packed_buffer¶
the (compressed) buffer.
If null, will be allocated during the run of the pipeline.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
size_t packed_alloc_size¶
used when re-using the same decode pipeline struct to know if chunk is changed size whether current buffer is large enough
-
void *unpacked_buffer¶
the decompressed buffer (unpacked_size from the chunk block info), but still packed into storage order, only needed for compressed files
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
size_t unpacked_alloc_size¶
used when re-using the same decode pipeline struct to know if chunk is changed size whether current buffer is large enough
-
void *packed_sample_count_table¶
for deep or other non-image data
packed sample table (i.e. compressed, raw on disk representation)
-
int32_t *sample_count_table¶
usable, native sample count table.
Depending on the flag set above, will be decoded to either a cumulative list (n, n+m, n+m+o, …), or an individual table (n, m, o, …). As an optimization, if the latter individual count table is chosen, an extra int32_t will be allocated at the end of the table to contain the total count of samples, so the table will be n+1 samples in size
-
void *scratch_buffer_1¶
a scratch buffer of unpacked_size for intermediate results
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
size_t scratch_alloc_size_1¶
used when re-using the same decode pipeline struct to know if chunk is changed size whether current buffer is large enough
-
void *scratch_buffer_2¶
some decompression routines may need a second scratch buffer (i.e.
zlib)
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
size_t scratch_alloc_size_2¶
used when re-using the same decode pipeline struct to know if chunk is changed size whether current buffer is large enough
-
void *(*alloc_fn)(enum transcoding_pipeline_buffer_id, size_t)¶
enables a custom allocator for the different buffers (i.e.
if decoding on a GPU). If NULL, will use the allocator from the context
-
void (*free_fn)(enum transcoding_pipeline_buffer_id, void*)¶
enables a custom allocator for the different buffers (i.e.
if decoding on a GPU). If NULL, will use the allocator from the context
-
exr_result_t (*read_fn)(struct _exr_decode_pipeline *pipeline)¶
Function chosen to read chunk data from the context.
Initialized to a default generic read routine, may be updated based on channel information when exr_choose_default_routines is called. This is done such that if the file is uncompressed and the output channel data is planar and the same type, the read function can read straight into the output channels, getting closer to a zero-copy operation. Otherwise a more traditional read, decompress, then unpack pipeline will be used with a default reader.
This is allowed to be overridden, but probably is not necessary in most scenarios
-
exr_result_t (*decompress_fn)(struct _exr_decode_pipeline *pipeline)¶
Function chosen based on the compression type of the part to decompress data.
If the user has a custom decompression method for the compression on this part, this can be changed after initialization.
If only compressed data is desired, then assign this to NULL after initialization.
-
exr_result_t (*realloc_nonimage_data_fn)(struct _exr_decode_pipeline *pipeline)¶
Function which can be provided if you have bespoke handling for non-image data and need to re-allocate the data to handle the about-to-be unpacked data.
If left NULL, will assume the memory pointed to by the channel pointers is sufficient
-
exr_result_t (*unpack_and_convert_fn)(struct _exr_decode_pipeline *pipeline)¶
Function chosen based on the output layout of the channels of the part to decompress data.
This will be NULL after initialization, until the user specifies a custom routine, or initializes the channel data and calls exr_choose_unpack_routine.
If only compressed data is desired, then leave or assign this to NULL after initialization.
-
exr_coding_channel_info_t _quick_chan_store[5]¶
Small stash of channel info values.
This is faster than calling malloc when the channel count in the part is small (RGBAZ), which is super common, however if there are a large number of channels, it will allocate space for that, so do not rely on this being used
-
exr_coding_channel_info_t *channels¶
-
typedef struct _exr_decode_pipeline exr_decode_pipeline_t¶
Structure meant to be used on a per-thread basis for reading exr data.
As should be obvious, this structure is NOT thread safe, but rather meant to be used by separate threads, which can all be accessing the same context concurrently.
-
exr_result_t exr_decoding_initialize(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, exr_decode_pipeline_t *decode)¶
Initialize the decoding pipeline structure with the channel info for the specified part, and the first block to be read.
NB: The unpack_and_convert_fn will be NULL after this. If that stage is desired, initialize the channel output information and call exr_choose_unpack_routine
-
exr_result_t exr_decoding_choose_default_routines(exr_const_context_t ctxt, int part_index, exr_decode_pipeline_t *decode)¶
Given an initialized decode pipeline, find appropriate functions to read and shuffle / convert data into the defined channel outputs.
Calling this is not required if custom routines will be used, or if just the raw compressed data is desired. Although in that scenario, it is probably easier to just read the chunk directly using exr_read_chunk
-
exr_result_t exr_decoding_update(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, exr_decode_pipeline_t *decode)¶
Given a decode pipeline previously initialized, update it for the new chunk to be read.
In this manner, memory buffers can be re-used to avoid continual malloc / free calls. Further, it allows the previous choices for the various functions to be quickly re-used.
-
exr_result_t exr_decoding_run(exr_const_context_t ctxt, int part_index, exr_decode_pipeline_t *decode)¶
Execute the decoding pipeline.
-
exr_result_t exr_decoding_destroy(exr_const_context_t ctxt, exr_decode_pipeline_t *decode)¶
Free any intermediate memory in the decoding pipeline.
This does not free any pointers referred to in the channel info areas, but rather only the intermediate buffers and memory needed for the structure itself.
Encoding¶
-
struct _exr_encode_pipeline¶
Structure meant to be used on a per-thread basis for writing exr data.
As should be obvious, this structure is NOT thread safe, but rather meant to be used by separate threads, which can all be accessing the same context concurrently.
Public Members
-
exr_coding_channel_info_t *channels¶
the output channel information for this chunk
User is expected to fill the channel pointers for the input channels. For writing, all channels must be initialized prior to using exr_choose_pack_routine. If a custom pack routine is written, that is up to the implementor.
Describes the channel information. This information is allocated dynamically during exr_initialize_encoding
-
uint16_t encode_flags¶
Encode flags to control the behavior.
-
int part_index¶
copy of the parameters given to the initialize / update for convenience
-
void *encoding_user_data¶
can be used by the user to pass custom context data through the encode pipeline
-
void *packed_buffer¶
the packed buffer where individual channels have been put into here.
If null, will be allocated during the run of the pipeline.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
uint64_t packed_bytes¶
differing from the allocation size, the number of actual bytes
-
size_t packed_alloc_size¶
used when re-using the same encode pipeline struct to know if chunk is changed size whether current buffer is large enough
If null, will be allocated during the run of the pipeline.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
int32_t *sample_count_table¶
for deep data.
NB: the members NOT const because we need to temporarily swap it to xdr order and restore it (to avoid a duplicate buffer allocation)
Depending on the flag set above, will be treated either as a cumulative list (n, n+m, n+m+o, …), or an individual table (n, m, o, …).
-
size_t sample_count_alloc_size¶
allocated table size (to avoid re-allocations).
Number of samples must always be width * height for the chunk
-
void *packed_sample_count_table¶
packed sample table (i.e.
compressed, raw on disk representation) for deep or other non-image data
-
size_t packed_sample_count_bytes¶
Number of bytes to write (actual size) for the packed_sample_count_table.
-
size_t packed_sample_count_alloc_size¶
Allocated size (to avoid re-allocations) for the packed_sample_count_table.
-
void *compressed_buffer¶
the compressed buffer, only needed for compressed files
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
size_t compressed_bytes¶
must be filled in as the pipeline runs to inform the writing software about the compressed size of the chunk (if it is an uncompressed file or the compression would make the file larger, it is expected to be the packed_buffer)
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to zero here. Be cognizant of any custom allocators.
-
size_t compressed_alloc_size¶
used when re-using the same encode pipeline struct to know if chunk is changed size whether current buffer is large enough
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to zero here. Be cognizant of any custom allocators.
-
void *scratch_buffer_1¶
a scratch buffer for intermediate results
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
size_t scratch_alloc_size_1¶
used when re-using the same encode pipeline struct to know if chunk is changed size whether current buffer is large enough
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
void *scratch_buffer_2¶
some compression routines may need a second scratch buffer
If null, will be allocated during the run of the pipeline when needed.
If the caller wishes to take control of the buffer, simple adopt the pointer and set it to null here. Be cognizant of any custom allocators.
-
size_t scratch_alloc_size_2¶
used when re-using the same encode pipeline struct to know if chunk is changed size whether current buffer is large enough
-
void *(*alloc_fn)(enum transcoding_pipeline_buffer_id, size_t)¶
enables a custom allocator for the different buffers (i.e.
if encoding on a GPU). If NULL, will use the allocator from the context
-
void (*free_fn)(enum transcoding_pipeline_buffer_id, void*)¶
enables a custom allocator for the different buffers (i.e.
if encoding on a GPU). If NULL, will use the allocator from the context
-
exr_result_t (*convert_and_pack_fn)(struct _exr_encode_pipeline *pipeline)¶
Function chosen based on the output layout of the channels of the part to decompress data.
If the user has a custom method for the compression on this part, this can be changed after initialization.
-
exr_result_t (*compress_fn)(struct _exr_encode_pipeline *pipeline)¶
Function chosen based on the compression type of the part to compress data.
If the user has a custom compression method for the compression type on this part, this can be changed after initialization.
-
exr_result_t (*yield_until_ready_fn)(struct _exr_encode_pipeline *pipeline)¶
This routine is used when waiting for other threads to finish writing previous chunks such that this thread can write this chunk.
This is used for parts which have a specified chunk ordering (increasing / decreasing y) and the chunks can not be written randomly (as could be true for uncompressed).
This enables the calling application to contribute thread time to other computation as needed, or just use something like pthread_yield().
By default, this routine will be assigned to a function which returns an error, failing the encode immediately. In this way, it assumes that there is only one thread being used for writing.
It is up to the user to provide an appropriate routine if performing multi-threaded writing.
-
exr_result_t (*write_fn)(struct _exr_encode_pipeline *pipeline)¶
Function chosen to write chunk data to the context.
This is allowed to be overridden, but probably is not necessary in most scenarios
-
exr_coding_channel_info_t _quick_chan_store[5]¶
Small stash of channel info values.
This is faster than calling malloc when the channel count in the part is small (RGBAZ), which is super common, however if there are a large number of channels, it will allocate space for that, so do not rely on this being used
-
exr_coding_channel_info_t *channels¶
-
typedef struct _exr_encode_pipeline exr_encode_pipeline_t¶
Structure meant to be used on a per-thread basis for writing exr data.
As should be obvious, this structure is NOT thread safe, but rather meant to be used by separate threads, which can all be accessing the same context concurrently.
-
struct exr_coding_channel_info_t¶
Structure for negotiating buffers when decoding / encoding chunks of data.
This is generic and meant to negotiate exr data bi-directionally, in that the same structure is used for both decoding and encoding chunks for read and write, respectively.
The first half of the structure will be filled by the library, and the caller is expected to fill the second half appropriately.
Public Members
-
const char *channel_name¶
channel name
This is provided as a convenient reference. Do not free, this refers to the internal data structure in the context.
-
int32_t height¶
number of lines for this channel in this chunk
May be 0 or less than overall image height based on sampling (i.e. when in 4:2:0 type sampling)
-
int32_t width¶
width in pixel count
May be 0 or less than overall image width based on sampling (i.e. 4:2:2 will have some channels have fewer values)
-
int32_t x_samples¶
horizontal subsampling information
-
int32_t y_samples¶
vertical subsampling information
-
uint8_t p_linear¶
linear flag from channel definition (used by b44)
-
int8_t bytes_per_element¶
how many bytes per pixel this channel consumes (i.e.
2 for float16, 4 for float32 / uint32)
-
uint16_t data_type¶
small form of exr_pixel_type_t enum (EXR_PIXEL_UINT/HALF/FLOAT)
-
int16_t user_bytes_per_element¶
how many bytes per pixel the input is or output should be (i.e.
2 for float16, 4 for float32 / uint32). Defaults to same size as input
-
uint16_t user_data_type¶
small form of exr_pixel_type_t enum (EXR_PIXEL_UINT/HALF/FLOAT).
Defaults to same type as input
-
int32_t user_pixel_stride¶
increment to get to next pixel
This is in bytes. Must be specified when the decode pointer is specified (and always for encode).
This is useful for implementing transcoding generically of planar or interleaved data. For planar data, where the layout is RRRRRGGGGGBBBBB, you can pass in 1 * bytes per component
-
int32_t user_line_stride¶
When lines > 1 for a chunk, this is the increment used to get from beginning of line to beginning of next line.
This is in bytes. Must be specified when the decode pointer is specified (and always for encode).
-
uint8_t *decode_to_ptr¶
-
const uint8_t *encode_from_ptr¶
-
union exr_coding_channel_info_t::[anonymous] [anonymous]¶
This data member has different requirements reading vs writing.
When reading, if this is left as NULL, the channel will be skipped during read and not filled in. During a write operation, this pointer is considered const and not modified. To make this more clear, a union is used here.
-
const char *channel_name¶
-
exr_result_t exr_encoding_initialize(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, exr_encode_pipeline_t *encode_pipe)¶
Initialize the encoding pipeline structure with the channel info for the specified part based on the chunk to be written.
NB: The pack_and_convert_fn will be NULL after this. If that stage is desired, initialize the channel output information and call exr_choose_unpack_routine
-
exr_result_t exr_encoding_choose_default_routines(exr_const_context_t ctxt, int part_index, exr_encode_pipeline_t *encode_pipe)¶
Given an initialized encode pipeline, find an appropriate function to shuffle and convert data into the defined channel outputs.
Calling this is not required if a custom routine will be used, or if just the raw decompressed data is desired.
-
exr_result_t exr_encoding_update(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, exr_encode_pipeline_t *encode_pipe)¶
Given a encode pipeline previously initialized, update it for the new chunk to be written.
In this manner, memory buffers can be re-used to avoid continual malloc / free calls. Further, it allows the previous choices for the various functions to be quickly re-used.
-
exr_result_t exr_encoding_run(exr_const_context_t ctxt, int part_index, exr_encode_pipeline_t *encode_pipe)¶
Execute the encoding pipeline.
-
exr_result_t exr_encoding_destroy(exr_const_context_t ctxt, exr_encode_pipeline_t *encode_pipe)¶
Free any intermediate memory in the encoding pipeline.
This does NOT free any pointers referred to in the channel info areas, but rather only the intermediate buffers and memory needed for the structure itself.
Attribute Values¶
-
struct exr_attr_chromaticities_t¶
struct to hold color chromaticities to interpret the tristimulus color values in the image data
-
struct exr_attr_keycode_t¶
struct to hold keycode information
-
enum exr_attribute_type_t¶
built-in / native attribute type enum
This will enable us to do a tagged type struct to generically store attributes.
Values:
-
enumerator EXR_ATTR_UNKNOWN¶
type indicating an error or uninitialized attribute
-
enumerator EXR_ATTR_BOX2I¶
integer region definition.
- See
exr_box2i
-
enumerator EXR_ATTR_BOX2F¶
float region definition.
- See
exr_box2f
-
enumerator EXR_ATTR_CHLIST¶
Definition of channels in file.
- See
exr_chlist_entry
-
enumerator EXR_ATTR_CHROMATICITIES¶
Values to specify color space of colors in file.
-
enumerator EXR_ATTR_COMPRESSION¶
uint8_t declaring compression present
-
enumerator EXR_ATTR_DOUBLE¶
double precision floating point number
-
enumerator EXR_ATTR_ENVMAP¶
uint8_t declaring environment map type
-
enumerator EXR_ATTR_FLOAT¶
a normal (4 byte) precision floating point number
-
enumerator EXR_ATTR_FLOAT_VECTOR¶
a list of normal (4 byte) precision floating point numbers
-
enumerator EXR_ATTR_INT¶
a 32-bit signed integer value
-
enumerator EXR_ATTR_KEYCODE¶
structure recording keycode
-
enumerator EXR_ATTR_LINEORDER¶
uint8_t declaring scanline ordering
-
enumerator EXR_ATTR_M33F¶
9 32-bit floats representing a 3x3 matrix
-
enumerator EXR_ATTR_M33D¶
9 64-bit floats representing a 3x3 matrix
-
enumerator EXR_ATTR_M44F¶
16 32-bit floats representing a 4x4 matrix
-
enumerator EXR_ATTR_M44D¶
16 64-bit floats representing a 4x4 matrix
-
enumerator EXR_ATTR_PREVIEW¶
2 unsigned ints followed by 4 x w x h uint8_t image
-
enumerator EXR_ATTR_RATIONAL¶
int followed by unsigned int
-
enumerator EXR_ATTR_STRING¶
int (length) followed by char string data
-
enumerator EXR_ATTR_STRING_VECTOR¶
0 or more text strings (int + string).
number is based on attribute size
-
enumerator EXR_ATTR_TILEDESC¶
2 unsigned ints xSize, ySize followed by mode
-
enumerator EXR_ATTR_TIMECODE¶
2 unsigned ints time and flags, user data
-
enumerator EXR_ATTR_V2I¶
pair of 32-bit integers
-
enumerator EXR_ATTR_V2F¶
pair of 32-bit floats
-
enumerator EXR_ATTR_V2D¶
pair of 64-bit floats
-
enumerator EXR_ATTR_V3I¶
set of 3 32-bit integers
-
enumerator EXR_ATTR_V3F¶
set of 3 32-bit floats
-
enumerator EXR_ATTR_V3D¶
set of 3 64-bit floats
-
enumerator EXR_ATTR_OPAQUE¶
user / unknown provided type
-
enumerator EXR_ATTR_LAST_KNOWN_TYPE¶
-
enumerator EXR_ATTR_UNKNOWN¶
-
struct exr_attribute_t¶
storage, name and type information for an attribute.
Attributes (metadata) for the file cause a surprising amount of overhead. It is not uncommon for a production-grade EXR to have many attributes. As such, the attribute struct is designed in a slightly more complicated manner. It is optimized to have the storage for that attribute: the struct itself, the name, the type, and the data all allocated as one block. Further, the type and standard names may use a static string to avoid allocating space for those as necessary with the pointers pointing to static strings (not to be freed). Finally, small values are optimized for.
Public Members
-
const char *name¶
name of the attribute
-
const char *type_name¶
string type name of the attribute
-
uint8_t name_length¶
length of name string (short flag is 31 max, long allows 255)
-
uint8_t type_name_length¶
length of type string (short flag is 31 max, long allows 255)
-
uint8_t pad[2]¶
-
exr_attribute_type_t type¶
enum of the attribute type
-
uint8_t uc¶
-
double d¶
-
float f¶
-
int32_t i¶
-
exr_attr_box2i_t *box2i¶
-
exr_attr_box2f_t *box2f¶
-
exr_attr_chlist_t *chlist¶
-
exr_attr_chromaticities_t *chromaticities¶
-
exr_attr_keycode_t *keycode¶
-
exr_attr_float_vector_t *floatvector¶
-
exr_attr_m33f_t *m33f¶
-
exr_attr_m33d_t *m33d¶
-
exr_attr_m44f_t *m44f¶
-
exr_attr_m44d_t *m44d¶
-
exr_attr_preview_t *preview¶
-
exr_attr_rational_t *rational¶
-
exr_attr_string_t *string¶
-
exr_attr_string_vector_t *stringvector¶
-
exr_attr_tiledesc_t *tiledesc¶
-
exr_attr_timecode_t *timecode¶
-
exr_attr_v2i_t *v2i¶
-
exr_attr_v2f_t *v2f¶
-
exr_attr_v2d_t *v2d¶
-
exr_attr_v3i_t *v3i¶
-
exr_attr_v3f_t *v3f¶
-
exr_attr_v3d_t *v3d¶
-
exr_attr_opaquedata_t *opaque¶
-
uint8_t *rawptr¶
-
union exr_attribute_t::[anonymous] [anonymous]¶
Union of pointers of different types that can be used to type pun to an appropriate type for builtins.
Do note that while this looks like a big thing, it is only the size of a single pointer. these are all pointers into some other data block storing the value you want, with the exception of the pod types which are just put in place (i.e. small value optimization)
The attribute type type should directly correlate to one of these entries
-
const char *name¶
-
struct exr_attr_opaquedata_t¶
Custom storage structure for opaque data.
Handlers for opaque types can be registered, then when a non-builtin type is encountered with a registered handler, the function pointers to unpack / pack it will be set up.
Public Members
-
int32_t size¶
-
int32_t unpacked_size¶
-
int32_t packed_alloc_size¶
if this is non-zero, the struct owns the data, if 0, is a const ref
-
uint8_t pad[4]¶
-
void *packed_data¶
-
void *unpacked_data¶
when an application wants to have custom data, they can store an unpacked form here which will be requested to be destroyed upon destruction of the attribute
-
exr_result_t (*unpack_func_ptr)(exr_context_t ctxt, const void *data, int32_t attrsize, int32_t *outsize, void **outbuffer)¶
-
exr_result_t (*pack_func_ptr)(exr_context_t ctxt, const void *data, int32_t datasize, int32_t *outsize, void *outbuffer)¶
-
void (*destroy_unpacked_func_ptr)(exr_context_t ctxt, void *data, int32_t attrsize)¶
-
int32_t size¶
Reading¶
-
exr_result_t exr_get_count(exr_const_context_t ctxt, int *count)¶
Query how many parts are in the file.
-
exr_result_t exr_get_name(exr_const_context_t ctxt, int part_index, const char **out)¶
Query the part name for the specified part.
NB: If this file is a single part file and name has not been set, this will return NULL.
-
exr_result_t exr_get_storage(exr_const_context_t ctxt, int part_index, exr_storage_t *out)¶
Query the storage type for the specified part.
-
exr_result_t exr_get_tile_levels(exr_const_context_t ctxt, int part_index, int32_t *levelsx, int32_t *levelsy)¶
Query how many levels are in the specified part.
If the part is a tiled part, fill in how many tile levels are present.
Return
ERR_SUCCESSon success, an error otherwise (i.e. if the part is not tiled).It is valid to pass NULL to either of the
levelsxorlevelsyarguments, which enables testing if this part is a tiled part, or if you don’t need both (i.e. in the case of a mip-level tiled image)
-
exr_result_t exr_get_tile_sizes(exr_const_context_t ctxt, int part_index, int levelx, int levely, int32_t *tilew, int32_t *tileh)¶
Query the tile size for a particular level in the specified part.
If the part is a tiled part, fill in the tile size for the specified part / level.
Return
ERR_SUCCESSonsuccess, an error otherwise (i.e. if the part is not tiled).It is valid to pass NULL to either of the
tilewortileharguments, which enables testing if this part is a tiled part, or if you don’t need both (i.e. in the case of a mip-level tiled image)
-
exr_result_t exr_get_level_sizes(exr_const_context_t ctxt, int part_index, int levelx, int levely, int32_t *levw, int32_t *levh)¶
Query the data sizes for a particular level in the specified part.
If the part is a tiled part, fill in the width / height for the specified levels.
Return
ERR_SUCCESSon success, an error otherwise (i.e. if the part is not tiled)It is valid to pass NULL to either of the
levworlevharguments, which enables testing if this part is a tiled part, or if you don’t need both for some reason
-
exr_result_t exr_get_chunk_count(exr_const_context_t ctxt, int part_index, int32_t *out)¶
Return the number of chunks contained in this part of the file.
As in the technical documentation for OpenEXR, the chunk is the generic term for a pixel data block. This is the atomic unit that this library uses to negotiate data to and from a context.
This should be used as a basis for splitting up how a file is processed. Depending on the compression, a different number of scanlines are encoded in each chunk, and since those need to be encoded / decoded as a block, the chunk should be the basis for I/O as well.
-
exr_result_t exr_get_scanlines_per_chunk(exr_const_context_t ctxt, int part_index, int32_t *out)¶
Return the number of scanlines chunks for this file part.
When iterating over a scanline file, this may be an easier metric for multi-threading or other access than only negotiating chunk counts, and so is provided as a utility.
-
exr_result_t exr_get_chunk_unpacked_size(exr_const_context_t ctxt, int part_index, uint64_t *out)¶
Return the maximum unpacked size of a chunk for the file part.
This may be used ahead of any actual reading of data, so can be used to pre-allocate buffers for multiple threads in one block or whatever your application may require.
-
exr_result_t exr_get_attribute_count(exr_const_context_t ctxt, int part_index, int32_t *count)¶
Query the count of attributes in a part.
-
exr_result_t exr_get_attribute_by_index(exr_const_context_t ctxt, int part_index, enum exr_attr_list_access_mode mode, int32_t idx, const exr_attribute_t **outattr)¶
Query a particular attribute by index.
-
exr_result_t exr_get_attribute_by_name(exr_const_context_t ctxt, int part_index, const char *name, const exr_attribute_t **outattr)¶
Query a particular attribute by name.
-
exr_result_t exr_get_attribute_list(exr_const_context_t ctxt, int part_index, enum exr_attr_list_access_mode mode, int32_t *count, const exr_attribute_t **outlist)¶
Query the list of attributes in a part.
This retrieves a list of attributes currently defined in a part.
If outlist is NULL, this function still succeeds, filling only the count. In this manner, the user can allocate memory for the list of attributes, then re-call this function to get the full list.
-
exr_result_t exr_attr_declare_by_type(exr_context_t ctxt, int part_index, const char *name, const char *type, exr_attribute_t **newattr)¶
Declare an attribute within the specified part.
Only valid when a file is opened for write.
-
exr_result_t exr_attr_declare(exr_context_t ctxt, int part_index, const char *name, exr_attribute_type_t type, exr_attribute_t **newattr)¶
Declare an attribute within the specified part.
Only valid when a file is opened for write.
-
exr_result_t exr_initialize_required_attr(exr_context_t ctxt, int part_index, const exr_attr_box2i_t *displayWindow, const exr_attr_box2i_t *dataWindow, float pixelaspectratio, const exr_attr_v2f_t *screenWindowCenter, float screenWindowWidth, exr_lineorder_t lineorder, exr_compression_t ctype)¶
Initialize all required attributes for all files.
NB: other file types do require other attributes, such as the tile description for a tiled file.
-
exr_result_t exr_initialize_required_attr_simple(exr_context_t ctxt, int part_index, int32_t width, int32_t height, exr_compression_t ctype)¶
Initialize all required attributes to default values:
displayWindowis set to (0, 0 ->width- 1,height- 1)dataWindowis set to (0, 0 ->width- 1,height- 1)pixelAspectRatiois set to 1.0screenWindowCenteris set to 0.f, 0.fscreenWindowWidthis set to 1.flineorderis set toINCREASING_Ycompressionis set toctype
-
exr_result_t exr_copy_unset_attributes(exr_context_t ctxt, int part_index, exr_const_context_t source, int src_part_index)¶
Copy the attributes from one part to another.
This allows one to quickly unassigned attributes from one source to another.
If an attribute in the source part has not been yet set in the destination part, the item will be copied over.
For example, when you add a part, the storage type and name attributes are required arguments to the definition of a new part, but channels has not yet been assigned. So by calling this with an input file as the source, you can copy the channel definitions (and any other unassigned attributes from the source).
-
exr_result_t exr_get_channels(exr_const_context_t ctxt, int part_index, const exr_attr_chlist_t **chlist)¶
Retrieve the list of channels.
-
exr_result_t exr_get_compression(exr_const_context_t ctxt, int part_index, exr_compression_t *compression)¶
Retrieve the compression method used for the specified part.
-
exr_result_t exr_get_data_window(exr_const_context_t ctxt, int part_index, exr_attr_box2i_t *out)¶
Retrieve the data window for the specified part.
-
exr_result_t exr_get_display_window(exr_const_context_t ctxt, int part_index, exr_attr_box2i_t *out)¶
Retrieve the display window for the specified part.
-
exr_result_t exr_get_lineorder(exr_const_context_t ctxt, int part_index, exr_lineorder_t *out)¶
Retrieve the line order for storing data in the specified part (use 0 for single part images)
-
exr_result_t exr_get_pixel_aspect_ratio(exr_const_context_t ctxt, int part_index, float *par)¶
Retrieve the pixel aspect ratio for the specified part (use 0 for single part images).
-
exr_result_t exr_get_screen_window_center(exr_const_context_t ctxt, int part_index, exr_attr_v2f_t *wc)¶
Retrieve the screen oriented window center for the specified part (use 0 for single part images)
-
exr_result_t exr_get_screen_window_width(exr_const_context_t ctxt, int part_index, float *out)¶
Retrieve the screen oriented window width for the specified part (use 0 for single part images)
-
exr_result_t exr_get_tile_descriptor(exr_const_context_t ctxt, int part_index, uint32_t *xsize, uint32_t *ysize, exr_tile_level_mode_t *level, exr_tile_round_mode_t *round)¶
Retrieve the tiling info for a tiled part (use 0 for single part images)
-
exr_result_t exr_get_version(exr_const_context_t ctxt, int part_index, int32_t *out)¶
-
exr_result_t exr_attr_get_box2i(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_box2i_t *outval)¶
-
exr_result_t exr_attr_get_box2f(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_box2f_t *outval)¶
-
exr_result_t exr_attr_get_channels(exr_const_context_t ctxt, int part_index, const char *name, const exr_attr_chlist_t **chlist)¶
Zero-copy query of channel data.
Do not free or manipulate the
chlistdata, or use after the lifetime of the context.
-
exr_result_t exr_attr_get_chromaticities(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_chromaticities_t *chroma)¶
-
exr_result_t exr_attr_get_compression(exr_const_context_t ctxt, int part_index, const char *name, exr_compression_t *out)¶
-
exr_result_t exr_attr_get_double(exr_const_context_t ctxt, int part_index, const char *name, double *out)¶
-
exr_result_t exr_attr_get_envmap(exr_const_context_t ctxt, int part_index, const char *name, exr_envmap_t *out)¶
-
exr_result_t exr_attr_get_float(exr_const_context_t ctxt, int part_index, const char *name, float *out)¶
-
exr_result_t exr_attr_get_float_vector(exr_const_context_t ctxt, int part_index, const char *name, int32_t *sz, const float **out)¶
Zero-copy query of float data.
Do not free or manipulate the
outdata, or use after the lifetime of the context.
-
exr_result_t exr_attr_get_int(exr_const_context_t ctxt, int part_index, const char *name, int32_t *out)¶
-
exr_result_t exr_attr_get_keycode(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_keycode_t *out)¶
-
exr_result_t exr_attr_get_lineorder(exr_const_context_t ctxt, int part_index, const char *name, exr_lineorder_t *out)¶
-
exr_result_t exr_attr_get_m33f(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_m33f_t *out)¶
-
exr_result_t exr_attr_get_m33d(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_m33d_t *out)¶
-
exr_result_t exr_attr_get_m44f(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_m44f_t *out)¶
-
exr_result_t exr_attr_get_m44d(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_m44d_t *out)¶
-
exr_result_t exr_attr_get_preview(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_preview_t *out)¶
-
exr_result_t exr_attr_get_rational(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_rational_t *out)¶
-
exr_result_t exr_attr_get_string(exr_const_context_t ctxt, int part_index, const char *name, int32_t *length, const char **out)¶
Zero-copy query of string value.
Do not modify the string pointed to by
out, and do not use after the lifetime of the context.
-
exr_result_t exr_attr_get_string_vector(exr_const_context_t ctxt, int part_index, const char *name, int32_t *size, const char **out)¶
Zero-copy query of string data.
Do not free the strings pointed to by the array.
Must provide
size.- Parameters
out – must be a
const char**array large enough to hold the string pointers for the string vector when provided.
-
exr_result_t exr_attr_get_tiledesc(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_tiledesc_t *out)¶
-
exr_result_t exr_attr_get_timecode(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_timecode_t *out)¶
-
exr_result_t exr_attr_get_v2i(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_v2i_t *out)¶
-
exr_result_t exr_attr_get_v2f(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_v2f_t *out)¶
-
exr_result_t exr_attr_get_v2d(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_v2d_t *out)¶
-
exr_result_t exr_attr_get_v3i(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_v3i_t *out)¶
-
exr_result_t exr_attr_get_v3f(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_v3f_t *out)¶
-
exr_result_t exr_attr_get_v3d(exr_const_context_t ctxt, int part_index, const char *name, exr_attr_v3d_t *out)¶
-
exr_result_t exr_attr_get_user(exr_const_context_t ctxt, int part_index, const char *name, const char **type, int32_t *size, const void **out)¶
Writing¶
-
exr_result_t exr_add_part(exr_context_t ctxt, const char *partname, exr_storage_t type, int *new_index)¶
Define a new part in the file.
-
int exr_add_channel(exr_context_t ctxt, int part_index, const char *name, exr_pixel_type_t ptype, exr_perceptual_treatment_t percept, int32_t xsamp, int32_t ysamp)¶
Define a new channel to the output file part.
The
perceptparameter is used for lossy compression techniques to indicate that the value represented is closer to linear (1) or closer to logarithmic (0). For r, g, b, luminance, this is normally 0
-
exr_result_t exr_set_channels(exr_context_t ctxt, int part_index, const exr_attr_chlist_t *channels)¶
Copy the channels from another source.
Useful if you are manually constructing the list or simply copying from an input file
-
exr_result_t exr_set_compression(exr_context_t ctxt, int part_index, exr_compression_t ctype)¶
Set the compression method used for the specified part.
-
int exr_set_data_window(exr_context_t ctxt, int part_index, const exr_attr_box2i_t *dw)¶
Set the data window for the specified part.
-
int exr_set_display_window(exr_context_t ctxt, int part_index, const exr_attr_box2i_t *dw)¶
Set the display window for the specified part.
-
exr_result_t exr_set_lineorder(exr_context_t ctxt, int part_index, exr_lineorder_t lo)¶
Set the line order for storing data in the specified part (use 0 for single part images)
-
exr_result_t exr_set_pixel_aspect_ratio(exr_context_t ctxt, int part_index, float par)¶
Set the pixel aspect ratio for the specified part (use 0 for single part images)
-
int exr_set_screen_window_center(exr_context_t ctxt, int part_index, const exr_attr_v2f_t *wc)¶
Set the screen oriented window center for the specified part (use 0 for single part images)
-
exr_result_t exr_set_screen_window_width(exr_context_t ctxt, int part_index, float ssw)¶
Set the screen oriented window width for the specified part (use 0 for single part images)
-
exr_result_t exr_set_tile_descriptor(exr_context_t ctxt, int part_index, uint32_t x_size, uint32_t y_size, exr_tile_level_mode_t level_mode, exr_tile_round_mode_t round_mode)¶
Set the tiling info for a tiled part (use 0 for single part images)
-
exr_result_t exr_set_name(exr_context_t ctxt, int part_index, const char *val)¶
-
exr_result_t exr_set_version(exr_context_t ctxt, int part_index, int32_t val)¶
-
exr_result_t exr_set_chunk_count(exr_context_t ctxt, int part_index, int32_t val)¶
-
exr_result_t exr_attr_set_box2i(exr_context_t ctxt, int part_index, const char *name, const exr_attr_box2i_t *val)¶
-
exr_result_t exr_attr_set_box2f(exr_context_t ctxt, int part_index, const char *name, const exr_attr_box2f_t *val)¶
-
exr_result_t exr_attr_set_channels(exr_context_t ctxt, int part_index, const char *name, const exr_attr_chlist_t *channels)¶
This allows one to quickly copy the channels from one file to another.
-
exr_result_t exr_attr_set_chromaticities(exr_context_t ctxt, int part_index, const char *name, const exr_attr_chromaticities_t *chroma)¶
-
exr_result_t exr_attr_set_compression(exr_context_t ctxt, int part_index, const char *name, exr_compression_t comp)¶
-
exr_result_t exr_attr_set_double(exr_context_t ctxt, int part_index, const char *name, double val)¶
-
exr_result_t exr_attr_set_envmap(exr_context_t ctxt, int part_index, const char *name, exr_envmap_t emap)¶
-
exr_result_t exr_attr_set_float(exr_context_t ctxt, int part_index, const char *name, float val)¶
-
exr_result_t exr_attr_set_float_vector(exr_context_t ctxt, int part_index, const char *name, int32_t sz, const float *vals)¶
-
exr_result_t exr_attr_set_int(exr_context_t ctxt, int part_index, const char *name, int32_t val)¶
-
exr_result_t exr_attr_set_keycode(exr_context_t ctxt, int part_index, const char *name, const exr_attr_keycode_t *kc)¶
-
exr_result_t exr_attr_set_lineorder(exr_context_t ctxt, int part_index, const char *name, exr_lineorder_t lo)¶
-
exr_result_t exr_attr_set_m33f(exr_context_t ctxt, int part_index, const char *name, const exr_attr_m33f_t *m)¶
-
exr_result_t exr_attr_set_m33d(exr_context_t ctxt, int part_index, const char *name, const exr_attr_m33d_t *m)¶
-
exr_result_t exr_attr_set_m44f(exr_context_t ctxt, int part_index, const char *name, const exr_attr_m44f_t *m)¶
-
exr_result_t exr_attr_set_m44d(exr_context_t ctxt, int part_index, const char *name, const exr_attr_m44d_t *m)¶
-
exr_result_t exr_attr_set_preview(exr_context_t ctxt, int part_index, const char *name, const exr_attr_preview_t *p)¶
-
exr_result_t exr_attr_set_rational(exr_context_t ctxt, int part_index, const char *name, const exr_attr_rational_t *r)¶
-
exr_result_t exr_attr_set_string(exr_context_t ctxt, int part_index, const char *name, const char *s)¶
-
exr_result_t exr_attr_set_string_vector(exr_context_t ctxt, int part_index, const char *name, int32_t size, const char **sv)¶
-
exr_result_t exr_attr_set_tiledesc(exr_context_t ctxt, int part_index, const char *name, const exr_attr_tiledesc_t *td)¶
-
exr_result_t exr_attr_set_timecode(exr_context_t ctxt, int part_index, const char *name, const exr_attr_timecode_t *tc)¶
-
exr_result_t exr_attr_set_v2i(exr_context_t ctxt, int part_index, const char *name, const exr_attr_v2i_t *v)¶
-
exr_result_t exr_attr_set_v2f(exr_context_t ctxt, int part_index, const char *name, const exr_attr_v2f_t *v)¶
-
exr_result_t exr_attr_set_v2d(exr_context_t ctxt, int part_index, const char *name, const exr_attr_v2d_t *v)¶
-
exr_result_t exr_attr_set_v3i(exr_context_t ctxt, int part_index, const char *name, const exr_attr_v3i_t *v)¶
-
exr_result_t exr_attr_set_v3f(exr_context_t ctxt, int part_index, const char *name, const exr_attr_v3f_t *v)¶
-
exr_result_t exr_attr_set_v3d(exr_context_t ctxt, int part_index, const char *name, const exr_attr_v3d_t *v)¶
-
exr_result_t exr_attr_set_user(exr_context_t ctxt, int part_index, const char *name, const char *type, int32_t size, const void *out)¶
Error Handling¶
-
enum exr_error_code_t¶
error codes that may be returned by various functions
Values:
-
enumerator EXR_ERR_SUCCESS¶
-
enumerator EXR_ERR_OUT_OF_MEMORY¶
-
enumerator EXR_ERR_MISSING_CONTEXT_ARG¶
-
enumerator EXR_ERR_INVALID_ARGUMENT¶
-
enumerator EXR_ERR_ARGUMENT_OUT_OF_RANGE¶
-
enumerator EXR_ERR_FILE_ACCESS¶
-
enumerator EXR_ERR_FILE_BAD_HEADER¶
-
enumerator EXR_ERR_NOT_OPEN_READ¶
-
enumerator EXR_ERR_NOT_OPEN_WRITE¶
-
enumerator EXR_ERR_HEADER_NOT_WRITTEN¶
-
enumerator EXR_ERR_READ_IO¶
-
enumerator EXR_ERR_WRITE_IO¶
-
enumerator EXR_ERR_NAME_TOO_LONG¶
-
enumerator EXR_ERR_MISSING_REQ_ATTR¶
-
enumerator EXR_ERR_INVALID_ATTR¶
-
enumerator EXR_ERR_NO_ATTR_BY_NAME¶
-
enumerator EXR_ERR_ATTR_TYPE_MISMATCH¶
-
enumerator EXR_ERR_ATTR_SIZE_MISMATCH¶
-
enumerator EXR_ERR_SCAN_TILE_MIXEDAPI¶
-
enumerator EXR_ERR_TILE_SCAN_MIXEDAPI¶
-
enumerator EXR_ERR_MODIFY_SIZE_CHANGE¶
-
enumerator EXR_ERR_ALREADY_WROTE_ATTRS¶
-
enumerator EXR_ERR_BAD_CHUNK_LEADER¶
-
enumerator EXR_ERR_CORRUPT_CHUNK¶
-
enumerator EXR_ERR_INCORRECT_PART¶
-
enumerator EXR_ERR_INCORRECT_CHUNK¶
-
enumerator EXR_ERR_USE_SCAN_DEEP_WRITE¶
-
enumerator EXR_ERR_USE_TILE_DEEP_WRITE¶
-
enumerator EXR_ERR_USE_SCAN_NONDEEP_WRITE¶
-
enumerator EXR_ERR_USE_TILE_NONDEEP_WRITE¶
-
enumerator EXR_ERR_INVALID_SAMPLE_DATA¶
-
enumerator EXR_ERR_FEATURE_NOT_IMPLEMENTED¶
-
enumerator EXR_ERR_UNKNOWN¶
-
enumerator EXR_ERR_SUCCESS¶
-
const char *exr_get_default_error_message(exr_result_t code)¶
Return a static string corresponding to the specified error code.
The string should not be freed (it is compiled into the binary).
-
const char *exr_get_error_code_as_string(exr_result_t code)¶
Return a static string corresponding to the specified error code.
The string should not be freed (it is compiled into the binary).