aboutsummaryrefslogtreecommitdiff
path: root/vendor/OpenEXRCore/exr_attr.odin
blob: aa508dfb3fca05b43d891b41e5a44ae61679471b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
package vendor_openexr

import "core:c"

// Enum declaring allowed values for \c u8 value stored in built-in compression type.
compression_t :: enum c.int {
	NONE  = 0,
	RLE   = 1,
	ZIPS  = 2,
	ZIP   = 3,
	PIZ   = 4,
	PXR24 = 5,
	B44   = 6,
	B44A  = 7,
	DWAA  = 8,
	DWAB  = 9,
}

// Enum declaring allowed values for \c u8 value stored in built-in env map type.
envmap_t :: enum c.int {
	LATLONG = 0,
	CUBE    = 1,
}

// Enum declaring allowed values for \c u8 value stored in \c lineOrder type.
lineorder_t :: enum c.int {
	INCREASING_Y = 0,
	DECREASING_Y = 1,
	RANDOM_Y     = 2,
}

// Enum declaring allowed values for part type.
storage_t :: enum c.int {
	SCANLINE = 0,  // Corresponds to type of \c scanlineimage.
	TILED,         // Corresponds to type of \c tiledimage.
	DEEP_SCANLINE, // Corresponds to type of \c deepscanline.
	DEEP_TILED,    // Corresponds to type of \c deeptile.
}

// @brief Enum representing what type of tile information is contained.
tile_level_mode_t :: enum c.int {
	ONE_LEVEL     = 0, // Single level of image data.
	MIPMAP_LEVELS = 1, // Mipmapped image data.
	RIPMAP_LEVELS = 2, // Ripmapped image data.
}

/** @brief Enum representing how to scale positions between levels. */
tile_round_mode_t :: enum c.int {
	DOWN = 0,
	UP   = 1,
}

/** @brief Enum capturing the underlying data type on a channel. */
pixel_type_t :: enum c.int {
	UINT  = 0,
	HALF  = 1,
	FLOAT = 2,
}

/* /////////////////////////////////////// */
/* First set of structs are data where we can read directly with no allocation needed... */

/** @brief Struct to hold color chromaticities to interpret the tristimulus color values in the image data. */
attr_chromaticities_t :: struct #packed {
	red_x:   f32,
	red_y:   f32,
	green_x: f32,
	green_y: f32,
	blue_x:  f32,
	blue_y:  f32,
	white_x: f32,
	white_y: f32,
}

/** @brief Struct to hold keycode information. */
attr_keycode_t :: struct #packed {
	film_mfc_code:   i32,
	film_type:       i32,
	prefix:          i32,
	count:           i32,
	perf_offset:     i32,
	perfs_per_frame: i32,
	perfs_per_count: i32,
}

/** @brief struct to hold a 32-bit floating-point 3x3 matrix. */
attr_m33f_t :: struct #packed {
	m: [9]f32,
}

/** @brief struct to hold a 64-bit floating-point 3x3 matrix. */
attr_m33d_t :: struct #packed {
	m: [9]f64,
}

/** @brief Struct to hold a 32-bit floating-point 4x4 matrix. */
attr_m44f_t :: struct #packed {
	m: [16]f32,
}

/** @brief Struct to hold a 64-bit floating-point 4x4 matrix. */
attr_m44d_t :: struct #packed {
	m: [16]f64,
}

/** @brief Struct to hold an integer ratio value. */
attr_rational_t :: struct #packed {
	num: i32,
	denom: u32,
}

/** @brief Struct to hold timecode information. */
attr_timecode_t :: struct #packed {
	time_and_flags: u32,
	user_data:      u32,
}

/** @brief Struct to hold a 2-element integer vector. */
attr_v2i_t :: distinct [2]i32

/** @brief Struct to hold a 2-element 32-bit float vector. */
attr_v2f_t :: distinct [2]f32

/** @brief Struct to hold a 2-element 64-bit float vector. */
attr_v2d_t :: distinct [2]f64

/** @brief Struct to hold a 3-element integer vector. */
attr_v3i_t :: distinct [3]i32

/** @brief Struct to hold a 3-element 32-bit float vector. */
attr_v3f_t :: distinct [3]f32

/** @brief Struct to hold a 3-element 64-bit float vector. */
attr_v3d_t :: distinct [3]f64

/** @brief Struct to hold an integer box/region definition. */
attr_box2i_t :: struct #packed {
	min: attr_v2i_t,
	max: attr_v2i_t,
}

/** @brief Struct to hold a floating-point box/region definition. */
attr_box2f_t:: struct #packed {
	min: attr_v2f_t,
	max: attr_v2f_t,
}

/** @brief Struct holding base tiledesc attribute type defined in spec
 *
 * NB: This is in a tightly packed area so it can be read directly, be
 * careful it doesn't become padded to the next \c uint32_t boundary.
 */
attr_tiledesc_t :: struct #packed {
	x_size: u32,
	y_size: u32,
	level_and_round: u8,
}

/** @brief Macro to access type of tiling from packed structure. */
GET_TILE_LEVEL_MODE :: #force_inline proc "c" (tiledesc: attr_tiledesc_t) -> tile_level_mode_t {
	return tile_level_mode_t(tiledesc.level_and_round & 0xf)
}
/** @brief Macro to access the rounding mode of tiling from packed structure. */
GET_TILE_ROUND_MODE :: #force_inline proc "c" (tiledesc: attr_tiledesc_t) -> tile_round_mode_t {
	return tile_round_mode_t((tiledesc.level_and_round >> 4) & 0xf)
}
/** @brief Macro to pack the tiling type and rounding mode into packed structure. */
PACK_TILE_LEVEL_ROUND :: #force_inline proc "c" (lvl: tile_level_mode_t, mode: tile_round_mode_t) -> u8 {
	return ((u8(mode) & 0xf) << 4) | (u8(lvl) & 0xf)
}


/* /////////////////////////////////////// */
/* Now structs that involve heap allocation to store data. */

/** Storage for a string. */
attr_string_t :: struct {
	length: i32,
	/** If this is non-zero, the string owns the data, if 0, is a const ref to a static string. */
	alloc_size: i32,

	str: cstring,
}

/** Storage for a string vector. */
attr_string_vector_t :: struct {
	n_strings: i32,
	/** If this is non-zero, the string vector owns the data, if 0, is a const ref. */
	alloc_size: i32,

	strings: [^]attr_string_t,
}

/** Float vector storage struct. */
attr_float_vector_t :: struct {
	length: i32,
	/** If this is non-zero, the float vector owns the data, if 0, is a const ref. */
	alloc_size: i32,

	arr: [^]f32,
}

/** 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).
 */
perceptual_treatment_t :: enum c.int {
	LOGARITHMIC = 0,
	LINEAR      = 1,
}

/** Individual channel information. */
attr_chlist_entry_t :: struct {
	name: attr_string_t,
	/** Data representation for these pixels: uint, half, float. */
	pixel_type: pixel_type_t,
	/** Possible values are 0 and 1 per docs perceptual_treatment_t. */
	p_linear: u8,
	reserved: [3]u8,
	x_sampling: i32,
	y_sampling: i32,
}

/** List of channel information (sorted alphabetically). */
attr_chlist_t :: struct {
	num_channels: c.int,
	num_alloced:  c.int,

	entries: [^]attr_chlist_entry_t,
}

/** @brief Struct to define attributes of an embedded preview image. */
attr_preview_t :: struct {
	width: u32,
	height: u32,
	/** If this is non-zero, the preview owns the data, if 0, is a const ref. */
	alloc_size: c.size_t,

	rgba: [^]u8,
}

/** 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.
 *
 * @sa register_attr_type_handler
 */
attr_opaquedata_t :: struct {
	size:              i32,
	unpacked_size:     i32,
	/** If this is non-zero, the struct owns the data, if 0, is a const ref. */
	packed_alloc_size: i32,
	pad: [4]u8,

	packed_data: rawptr,

	/** 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.
	 */
	unpacked_data: rawptr,

	/** An application can register an attribute handler which then
	 * fills in these function pointers. This allows a user to delay
	 * the expansion of the custom type until access is desired, and
	 * similarly, to delay the packing of the data until write time.
	 */
	unpack_func_ptr: proc "c" (
		ctxt: context_t,
		data: rawptr,
		attrsize: i32,
		outsize: ^i32,
		outbuffer: ^rawptr) -> result_t,
	pack_func_ptr: proc "c" (
		ctxt: context_t,
		data: rawptr,
		datasize: i32,
		outsize: ^i32,
		outbuffer: rawptr) -> result_t,
	destroy_unpacked_func_ptr: proc "c" (
		ctxt: context_t, data: rawptr, attrsize: i32),
}

/* /////////////////////////////////////// */

/** @brief Built-in/native attribute type enum.
 *
 * This will enable us to do a tagged type struct to generically store
 * attributes.
 */
attribute_type_t :: enum c.int {
	UNKNOWN = 0,      // Type indicating an error or uninitialized attribute.
	BOX2I,            // Integer region definition. @see attr_box2i_t.
	BOX2F,            // Float region definition. @see attr_box2f_t.
	CHLIST,           // Definition of channels in file @see chlist_entry.
	CHROMATICITIES,   // Values to specify color space of colors in file @see attr_chromaticities_t.
	COMPRESSION,      // ``u8`` declaring compression present.
	DOUBLE,           // Double precision floating point number.
	ENVMAP,           // ``u8`` declaring environment map type.
	FLOAT,            // Normal (4 byte) precision floating point number.
	FLOAT_VECTOR,     // List of normal (4 byte) precision floating point numbers.
	INT,              // 32-bit signed integer value.
	KEYCODE,          // Struct recording keycode @see attr_keycode_t.
	LINEORDER,        // ``u8`` declaring scanline ordering.
	M33F,             // 9 32-bit floats representing a 3x3 matrix.
	M33D,             // 9 64-bit floats representing a 3x3 matrix.
	M44F,             // 16 32-bit floats representing a 4x4 matrix.
	M44D,             // 16 64-bit floats representing a 4x4 matrix.
	PREVIEW,          // 2 ``unsigned ints`` followed by 4 x w x h ``u8`` image.
	RATIONAL,         // \c int followed by ``unsigned int``
	STRING,           // ``int`` (length) followed by char string data.
	STRING_VECTOR,    // 0 or more text strings (int + string). number is based on attribute size.
	TILEDESC,         // 2 ``unsigned ints`` ``xSize``, ``ySize`` followed by mode.
	TIMECODE,         // 2 ``unsigned ints`` time and flags, user data.
	V2I,              // Pair of 32-bit integers.
	V2F,              // Pair of 32-bit floats.
	V2D,              // Pair of 64-bit floats.
	V3I,              // Set of 3 32-bit integers.
	V3F,              // Set of 3 32-bit floats.
	V3D,              // Set of 3 64-bit floats.
	DEEP_IMAGE_STATE, // ``uint8_t`` declaring deep image state.
	OPAQUE,           // User/unknown provided type.
}

/** @brief 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.
 */
attribute_t :: struct {
	/** Name of the attribute. */
	name:             cstring,
	/** String type name of the attribute. */
	type_name:        cstring,
	/** Length of name string (short flag is 31 max, long allows 255). */
	name_length:      u8,
	/** Length of type string (short flag is 31 max, long allows 255). */
	type_name_length: u8,

	pad: [2]u8,

	/** Enum of the attribute type. */
	type: attribute_type_t,

	/** 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 \c type should directly correlate to one
	 * of these entries.
	 */
	using _: struct #raw_union {
		// NB: not pointers for POD types
		uc: u8,
		d: f64,
		f: f32,
		i: i32,

		box2i:          ^attr_box2i_t,
		box2f:          ^attr_box2f_t,
		chlist:         ^attr_chlist_t,
		chromaticities: ^attr_chromaticities_t,
		keycode:        ^attr_keycode_t,
		floatvector:    ^attr_float_vector_t,
		m33f:           ^attr_m33f_t,
		m33d:           ^attr_m33d_t,
		m44f:           ^attr_m44f_t,
		m44d:           ^attr_m44d_t,
		preview:        ^attr_preview_t,
		rational:       ^attr_rational_t,
		string:         ^attr_string_t,
		stringvector:   ^attr_string_vector_t,
		tiledesc:       ^attr_tiledesc_t,
		timecode:       ^attr_timecode_t,
		v2i:            ^attr_v2i_t,
		v2f:            ^attr_v2f_t,
		v2d:            ^attr_v2d_t,
		v3i:            ^attr_v3i_t,
		v3f:            ^attr_v3f_t,
		v3d:            ^attr_v3d_t,
		opaque:         ^attr_opaquedata_t,
		rawptr:         ^u8,
	},
}