1 /*
2 ** SPDX-License-Identifier: BSD-3-Clause
3 ** Copyright Contributors to the OpenEXR Project.
4 */
5 
6 #ifndef OPENEXR_ATTR_H
7 #define OPENEXR_ATTR_H
8 
9 #include "openexr_context.h"
10 
11 #include <stddef.h>
12 #include <stdint.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /** @file */
19 
20 /**
21  * @defgroup AttributeTypes Attribute/metadata value types and struct declarations
22  *
23  * @brief These are a group of enum values defining valid values for
24  * some attributes and then associated structs for other types.
25  *
26  * Some of these types will be directly representable/storable in
27  * the file, some not. There is some overlap here with Imath, and they
28  * should be kept in the same order for compatibility. However do note
29  * that these are just the raw data, and no useful functions are
30  * declared at this layer, that is what Imath is for.
31  *
32  * @{
33  */
34 
35 /** Enum declaring allowed values for \c uint8_t value stored in built-in compression type. */
36 typedef enum
37 {
38     EXR_COMPRESSION_NONE  = 0,
39     EXR_COMPRESSION_RLE   = 1,
40     EXR_COMPRESSION_ZIPS  = 2,
41     EXR_COMPRESSION_ZIP   = 3,
42     EXR_COMPRESSION_PIZ   = 4,
43     EXR_COMPRESSION_PXR24 = 5,
44     EXR_COMPRESSION_B44   = 6,
45     EXR_COMPRESSION_B44A  = 7,
46     EXR_COMPRESSION_DWAA  = 8,
47     EXR_COMPRESSION_DWAB  = 9,
48     EXR_COMPRESSION_LAST_TYPE /**< Invalid value, provided for range checking. */
49 } exr_compression_t;
50 
51 /** Enum declaring allowed values for \c uint8_t value stored in built-in env map type. */
52 typedef enum
53 {
54     EXR_ENVMAP_LATLONG = 0,
55     EXR_ENVMAP_CUBE    = 1,
56     EXR_ENVMAP_LAST_TYPE /**< Invalid value, provided for range checking. */
57 } exr_envmap_t;
58 
59 /** Enum declaring allowed values for \c uint8_t value stored in \c lineOrder type. */
60 typedef enum
61 {
62     EXR_LINEORDER_INCREASING_Y = 0,
63     EXR_LINEORDER_DECREASING_Y = 1,
64     EXR_LINEORDER_RANDOM_Y     = 2,
65     EXR_LINEORDER_LAST_TYPE /**< Invalid value, provided for range checking. */
66 } exr_lineorder_t;
67 
68 /** Enum declaring allowed values for part type. */
69 typedef enum
70 {
71     EXR_STORAGE_SCANLINE = 0,  /**< Corresponds to type of \c scanlineimage. */
72     EXR_STORAGE_TILED,         /**< Corresponds to type of \c tiledimage. */
73     EXR_STORAGE_DEEP_SCANLINE, /**< Corresponds to type of \c deepscanline. */
74     EXR_STORAGE_DEEP_TILED,    /**< Corresponds to type of \c deeptile. */
75     EXR_STORAGE_LAST_TYPE      /**< Invalid value, provided for range checking. */
76 } exr_storage_t;
77 
78 /** @brief Enum representing what type of tile information is contained. */
79 typedef enum
80 {
81     EXR_TILE_ONE_LEVEL     = 0, /**< Single level of image data. */
82     EXR_TILE_MIPMAP_LEVELS = 1, /**< Mipmapped image data. */
83     EXR_TILE_RIPMAP_LEVELS = 2, /**< Ripmapped image data. */
84     EXR_TILE_LAST_TYPE          /**< Invalid value, provided for range checking. */
85 } exr_tile_level_mode_t;
86 
87 /** @brief Enum representing how to scale positions between levels. */
88 typedef enum
89 {
90     EXR_TILE_ROUND_DOWN = 0,
91     EXR_TILE_ROUND_UP   = 1,
92     EXR_TILE_ROUND_LAST_TYPE
93 } exr_tile_round_mode_t;
94 
95 /** @brief Enum capturing the underlying data type on a channel. */
96 typedef enum
97 {
98     EXR_PIXEL_UINT  = 0,
99     EXR_PIXEL_HALF  = 1,
100     EXR_PIXEL_FLOAT = 2,
101     EXR_PIXEL_LAST_TYPE
102 } exr_pixel_type_t;
103 
104 /* /////////////////////////////////////// */
105 /* First set of structs are data where we can read directly with no allocation needed... */
106 
107 /* Most are naturally aligned, but force some of these
108  * structs to be tightly packed
109  */
110 #pragma pack(push, 1)
111 
112 /** @brief Struct to hold color chromaticities to interpret the tristimulus color values in the image data. */
113 typedef struct
114 {
115     float red_x;
116     float red_y;
117     float green_x;
118     float green_y;
119     float blue_x;
120     float blue_y;
121     float white_x;
122     float white_y;
123 } exr_attr_chromaticities_t;
124 
125 /** @brief Struct to hold keycode information. */
126 typedef struct
127 {
128     int32_t film_mfc_code;
129     int32_t film_type;
130     int32_t prefix;
131     int32_t count;
132     int32_t perf_offset;
133     int32_t perfs_per_frame;
134     int32_t perfs_per_count;
135 } exr_attr_keycode_t;
136 
137 /** @brief struct to hold a 32-bit floating-point 3x3 matrix. */
138 typedef struct
139 {
140     float m[9];
141 } exr_attr_m33f_t;
142 
143 /** @brief struct to hold a 64-bit floating-point 3x3 matrix. */
144 typedef struct
145 {
146     double m[9];
147 } exr_attr_m33d_t;
148 
149 /** @brief Struct to hold a 32-bit floating-point 4x4 matrix. */
150 typedef struct
151 {
152     float m[16];
153 } exr_attr_m44f_t;
154 
155 /** @brief Struct to hold a 64-bit floating-point 4x4 matrix. */
156 typedef struct
157 {
158     double m[16];
159 } exr_attr_m44d_t;
160 
161 /** @brief Struct to hold an integer ratio value. */
162 typedef struct
163 {
164     int32_t  num;
165     uint32_t denom;
166 } exr_attr_rational_t;
167 
168 /** @brief Struct to hold timecode information. */
169 typedef struct
170 {
171     uint32_t time_and_flags;
172     uint32_t user_data;
173 } exr_attr_timecode_t;
174 
175 /** @brief Struct to hold a 2-element integer vector. */
176 typedef struct
177 {
178     union
179     {
180         struct
181         {
182             int32_t x, y;
183         };
184         int32_t arr[2];
185     };
186 } exr_attr_v2i_t;
187 
188 /** @brief Struct to hold a 2-element 32-bit float vector. */
189 typedef struct
190 {
191     union
192     {
193         struct
194         {
195             float x, y;
196         };
197         float arr[2];
198     };
199 } exr_attr_v2f_t;
200 
201 /** @brief Struct to hold a 2-element 64-bit float vector. */
202 typedef struct
203 {
204     union
205     {
206         struct
207         {
208             double x, y;
209         };
210         double arr[2];
211     };
212 } exr_attr_v2d_t;
213 
214 /** @brief Struct to hold a 3-element integer vector. */
215 typedef struct
216 {
217     union
218     {
219         struct
220         {
221             int32_t x, y, z;
222         };
223         int32_t arr[3];
224     };
225 } exr_attr_v3i_t;
226 
227 /** @brief Struct to hold a 3-element 32-bit float vector. */
228 typedef struct
229 {
230     union
231     {
232         struct
233         {
234             float x, y, z;
235         };
236         float arr[3];
237     };
238 } exr_attr_v3f_t;
239 
240 /** @brief Struct to hold a 3-element 64-bit float vector. */
241 typedef struct
242 {
243     union
244     {
245         struct
246         {
247             double x, y, z;
248         };
249         double arr[3];
250     };
251 } exr_attr_v3d_t;
252 
253 /** @brief Struct to hold an integer box/region definition. */
254 typedef struct
255 {
256     exr_attr_v2i_t min;
257     exr_attr_v2i_t max;
258 } exr_attr_box2i_t;
259 
260 /** @brief Struct to hold a floating-point box/region definition. */
261 typedef struct
262 {
263     exr_attr_v2f_t min;
264     exr_attr_v2f_t max;
265 } exr_attr_box2f_t;
266 
267 /** @brief Struct holding base tiledesc attribute type defined in spec
268  *
269  * NB: This is in a tightly packed area so it can be read directly, be
270  * careful it doesn't become padded to the next \c uint32_t boundary.
271  */
272 typedef struct
273 {
274     uint32_t x_size;
275     uint32_t y_size;
276     uint8_t  level_and_round;
277 } exr_attr_tiledesc_t;
278 
279 /** @brief Macro to access type of tiling from packed structure. */
280 #define EXR_GET_TILE_LEVEL_MODE(tiledesc)                                      \
281     ((exr_tile_level_mode_t) (((tiledesc).level_and_round) & 0xF))
282 /** @brief Macro to access the rounding mode of tiling from packed structure. */
283 #define EXR_GET_TILE_ROUND_MODE(tiledesc)                                      \
284     ((exr_tile_round_mode_t) ((((tiledesc).level_and_round) >> 4) & 0xF))
285 /** @brief Macro to pack the tiling type and rounding mode into packed structure. */
286 #define EXR_PACK_TILE_LEVEL_ROUND(lvl, mode)                                   \
287     ((uint8_t) ((((uint8_t) ((mode) &0xF) << 4)) | ((uint8_t) ((lvl) &0xF))))
288 
289 #pragma pack(pop)
290 
291 /* /////////////////////////////////////// */
292 /* Now structs that involve heap allocation to store data. */
293 
294 /** Storage for a string. */
295 typedef struct
296 {
297     int32_t length;
298     /** If this is non-zero, the string owns the data, if 0, is a const ref to a static string. */
299     int32_t alloc_size;
300 
301     const char* str;
302 } exr_attr_string_t;
303 
304 /** Storage for a string vector. */
305 typedef struct
306 {
307     int32_t n_strings;
308     /** If this is non-zero, the string vector owns the data, if 0, is a const ref. */
309     int32_t alloc_size;
310 
311     const exr_attr_string_t* strings;
312 } exr_attr_string_vector_t;
313 
314 /** Float vector storage struct. */
315 typedef struct
316 {
317     int32_t length;
318     /** If this is non-zero, the float vector owns the data, if 0, is a const ref. */
319     int32_t alloc_size;
320 
321     const float* arr;
322 } exr_attr_float_vector_t;
323 
324 /** Hint for lossy compression methods about how to treat values
325  * (logarithmic or linear), meaning a human sees values like R, G, B,
326  * luminance difference between 0.1 and 0.2 as about the same as 1.0
327  * to 2.0 (logarithmic), where chroma coordinates are closer to linear
328  * (0.1 and 0.2 is about the same difference as 1.0 and 1.1).
329  */
330 typedef enum
331 {
332     EXR_PERCEPTUALLY_LOGARITHMIC  = 0,
333     EXR_PERCEPTUALLY_LINEAR   = 1
334 } exr_perceptual_treatment_t;
335 
336 /** Individual channel information. */
337 typedef struct
338 {
339     exr_attr_string_t name;
340     /** Data representation for these pixels: uint, half, float. */
341     exr_pixel_type_t pixel_type;
342     /** Possible values are 0 and 1 per docs exr_perceptual_treatment_t. */
343     uint8_t p_linear;
344     uint8_t reserved[3];
345     int32_t x_sampling;
346     int32_t y_sampling;
347 } exr_attr_chlist_entry_t;
348 
349 /** List of channel information (sorted alphabetically). */
350 typedef struct
351 {
352     int num_channels;
353     int num_alloced;
354 
355     const exr_attr_chlist_entry_t* entries;
356 } exr_attr_chlist_t;
357 
358 /** @brief Struct to define attributes of an embedded preview image. */
359 typedef struct
360 {
361     uint32_t width;
362     uint32_t height;
363     /** If this is non-zero, the preview owns the data, if 0, is a const ref. */
364     size_t alloc_size;
365 
366     const uint8_t* rgba;
367 } exr_attr_preview_t;
368 
369 /** Custom storage structure for opaque data.
370  *
371  * Handlers for opaque types can be registered, then when a
372  * non-builtin type is encountered with a registered handler, the
373  * function pointers to unpack/pack it will be set up.
374  *
375  * @sa exr_register_attr_type_handler
376  */
377 typedef struct
378 {
379     int32_t size;
380     int32_t unpacked_size;
381     /** If this is non-zero, the struct owns the data, if 0, is a const ref. */
382     int32_t packed_alloc_size;
383     uint8_t pad[4];
384 
385     void*   packed_data;
386 
387     /** When an application wants to have custom data, they can store
388      * an unpacked form here which will be requested to be destroyed
389      * upon destruction of the attribute.
390      */
391     void* unpacked_data;
392 
393     /** An application can register an attribute handler which then
394      * fills in these function pointers. This allows a user to delay
395      * the expansion of the custom type until access is desired, and
396      * similarly, to delay the packing of the data until write time.
397      */
398     exr_result_t (*unpack_func_ptr) (
399         exr_context_t ctxt,
400         const void*   data,
401         int32_t       attrsize,
402         int32_t*      outsize,
403         void**        outbuffer);
404     exr_result_t (*pack_func_ptr) (
405         exr_context_t ctxt,
406         const void*   data,
407         int32_t       datasize,
408         int32_t*      outsize,
409         void*         outbuffer);
410     void (*destroy_unpacked_func_ptr) (
411         exr_context_t ctxt, void* data, int32_t attrsize);
412 } exr_attr_opaquedata_t;
413 
414 /* /////////////////////////////////////// */
415 
416 /** @brief Built-in/native attribute type enum.
417  *
418  * This will enable us to do a tagged type struct to generically store
419  * attributes.
420  */
421 typedef enum
422 {
423     EXR_ATTR_UNKNOWN =
424         0,           /**< Type indicating an error or uninitialized attribute. */
425     EXR_ATTR_BOX2I,  /**< Integer region definition. @see exr_attr_box2i_t. */
426     EXR_ATTR_BOX2F,  /**< Float region definition. @see exr_attr_box2f_t. */
427     EXR_ATTR_CHLIST, /**< Definition of channels in file @see exr_chlist_entry. */
428     EXR_ATTR_CHROMATICITIES, /**< Values to specify color space of colors in file @see exr_attr_chromaticities_t. */
429     EXR_ATTR_COMPRESSION,    /**< ``uint8_t`` declaring compression present. */
430     EXR_ATTR_DOUBLE,         /**< Double precision floating point number. */
431     EXR_ATTR_ENVMAP,         /**< ``uint8_t`` declaring environment map type. */
432     EXR_ATTR_FLOAT, /**< Normal (4 byte) precision floating point number. */
433     EXR_ATTR_FLOAT_VECTOR, /**< List of normal (4 byte) precision floating point numbers. */
434     EXR_ATTR_INT,     /**< 32-bit signed integer value. */
435     EXR_ATTR_KEYCODE, /**< Struct recording keycode @see exr_attr_keycode_t. */
436     EXR_ATTR_LINEORDER, /**< ``uint8_t`` declaring scanline ordering. */
437     EXR_ATTR_M33F,      /**< 9 32-bit floats representing a 3x3 matrix. */
438     EXR_ATTR_M33D,      /**< 9 64-bit floats representing a 3x3 matrix. */
439     EXR_ATTR_M44F,      /**< 16 32-bit floats representing a 4x4 matrix. */
440     EXR_ATTR_M44D,      /**< 16 64-bit floats representing a 4x4 matrix. */
441     EXR_ATTR_PREVIEW, /**< 2 ``unsigned ints`` followed by 4 x w x h ``uint8_t`` image. */
442     EXR_ATTR_RATIONAL, /**< \c int followed by ``unsigned int`` */
443     EXR_ATTR_STRING,   /**< ``int`` (length) followed by char string data. */
444     EXR_ATTR_STRING_VECTOR, /**< 0 or more text strings (int + string). number is based on attribute size. */
445     EXR_ATTR_TILEDESC, /**< 2 ``unsigned ints`` ``xSize``, ``ySize`` followed by mode. */
446     EXR_ATTR_TIMECODE, /**< 2 ``unsigned ints`` time and flags, user data. */
447     EXR_ATTR_V2I,      /**< Pair of 32-bit integers. */
448     EXR_ATTR_V2F,      /**< Pair of 32-bit floats. */
449     EXR_ATTR_V2D,      /**< Pair of 64-bit floats. */
450     EXR_ATTR_V3I,      /**< Set of 3 32-bit integers. */
451     EXR_ATTR_V3F,      /**< Set of 3 32-bit floats. */
452     EXR_ATTR_V3D,      /**< Set of 3 64-bit floats. */
453     EXR_ATTR_OPAQUE,   /**< User/unknown provided type. */
454     EXR_ATTR_LAST_KNOWN_TYPE
455 } exr_attribute_type_t;
456 
457 /** @brief Storage, name and type information for an attribute.
458  *
459  * Attributes (metadata) for the file cause a surprising amount of
460  * overhead. It is not uncommon for a production-grade EXR to have
461  * many attributes. As such, the attribute struct is designed in a
462  * slightly more complicated manner. It is optimized to have the
463  * storage for that attribute: the struct itself, the name, the type,
464  * and the data all allocated as one block. Further, the type and
465  * standard names may use a static string to avoid allocating space
466  * for those as necessary with the pointers pointing to static strings
467  * (not to be freed). Finally, small values are optimized for.
468  */
469 typedef struct
470 {
471     /** Name of the attribute. */
472     const char* name;
473     /** String type name of the attribute. */
474     const char* type_name;
475     /** Length of name string (short flag is 31 max, long allows 255). */
476     uint8_t name_length;
477     /** Length of type string (short flag is 31 max, long allows 255). */
478     uint8_t type_name_length;
479 
480     uint8_t pad[2];
481 
482     /** Enum of the attribute type. */
483     exr_attribute_type_t type;
484 
485     /** Union of pointers of different types that can be used to type
486      * pun to an appropriate type for builtins. Do note that while
487      * this looks like a big thing, it is only the size of a single
488      * pointer.  These are all pointers into some other data block
489      * storing the value you want, with the exception of the pod types
490      * which are just put in place (i.e. small value optimization).
491      *
492      * The attribute type \c type should directly correlate to one
493      * of these entries.
494      */
495     union
496     {
497         // NB: not pointers for POD types
498         uint8_t uc;
499         double  d;
500         float   f;
501         int32_t i;
502 
503         exr_attr_box2i_t*          box2i;
504         exr_attr_box2f_t*          box2f;
505         exr_attr_chlist_t*         chlist;
506         exr_attr_chromaticities_t* chromaticities;
507         exr_attr_keycode_t*        keycode;
508         exr_attr_float_vector_t*   floatvector;
509         exr_attr_m33f_t*           m33f;
510         exr_attr_m33d_t*           m33d;
511         exr_attr_m44f_t*           m44f;
512         exr_attr_m44d_t*           m44d;
513         exr_attr_preview_t*        preview;
514         exr_attr_rational_t*       rational;
515         exr_attr_string_t*         string;
516         exr_attr_string_vector_t*  stringvector;
517         exr_attr_tiledesc_t*       tiledesc;
518         exr_attr_timecode_t*       timecode;
519         exr_attr_v2i_t*            v2i;
520         exr_attr_v2f_t*            v2f;
521         exr_attr_v2d_t*            v2d;
522         exr_attr_v3i_t*            v3i;
523         exr_attr_v3f_t*            v3f;
524         exr_attr_v3d_t*            v3d;
525         exr_attr_opaquedata_t*     opaque;
526         uint8_t*                   rawptr;
527     };
528 } exr_attribute_t;
529 
530 /** @} */
531 
532 #ifdef __cplusplus
533 } /* extern "C" */
534 #endif
535 
536 #endif /* OPENEXR_ATTR_H */
537