/src/openexr/src/lib/OpenEXR/ImfContext.cpp
Line | Count | Source |
1 | | // |
2 | | // SPDX-License-Identifier: BSD-3-Clause |
3 | | // Copyright (c) Contributors to the OpenEXR Project. |
4 | | // |
5 | | |
6 | | #include "ImfContext.h" |
7 | | |
8 | | #include "openexr.h" |
9 | | |
10 | | #include "Iex.h" |
11 | | |
12 | | // TODO: remove these once we've cleared the legacy stream need |
13 | | #include "ImfIO.h" |
14 | | #include "ImfStdIO.h" |
15 | | #include <mutex> |
16 | | |
17 | | #include <string.h> |
18 | | |
19 | | #include <ImfBoxAttribute.h> |
20 | | #include <ImfChannelListAttribute.h> |
21 | | #include <ImfChromaticitiesAttribute.h> |
22 | | #include <ImfCompressionAttribute.h> |
23 | | #include <ImfCompressor.h> |
24 | | #include <ImfDeepImageStateAttribute.h> |
25 | | #include <ImfDoubleAttribute.h> |
26 | | #include <ImfDwaCompressor.h> |
27 | | #include <ImfEnvmapAttribute.h> |
28 | | #include <ImfFloatAttribute.h> |
29 | | #include <ImfFloatVectorAttribute.h> |
30 | | #include <ImfIDManifestAttribute.h> |
31 | | #include <ImfIntAttribute.h> |
32 | | #include <ImfKeyCodeAttribute.h> |
33 | | #include <ImfLineOrderAttribute.h> |
34 | | #include <ImfMatrixAttribute.h> |
35 | | #include <ImfOpaqueAttribute.h> |
36 | | #include <ImfPreviewImageAttribute.h> |
37 | | #include <ImfRationalAttribute.h> |
38 | | #include <ImfStringAttribute.h> |
39 | | #include <ImfStringVectorAttribute.h> |
40 | | #include <ImfTileDescriptionAttribute.h> |
41 | | #include <ImfTimeCodeAttribute.h> |
42 | | #include <ImfVecAttribute.h> |
43 | | |
44 | | OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER |
45 | | |
46 | | namespace |
47 | | { |
48 | | |
49 | | class MemAttrStream : public OPENEXR_IMF_NAMESPACE::IStream |
50 | | { |
51 | | public: |
52 | | MemAttrStream (const exr_attr_opaquedata_t *opaque) |
53 | 2.16k | : IStream ("<mem_attr>"), |
54 | 2.16k | _data (static_cast<char*> (opaque->packed_data)), |
55 | 2.16k | _sz (static_cast<uint64_t> (opaque->size)), |
56 | 2.16k | _pos (0) |
57 | 2.16k | {} |
58 | | |
59 | 0 | ~MemAttrStream () override {} |
60 | | |
61 | 0 | bool isMemoryMapped () const override { return true; } |
62 | | |
63 | | bool read (char c[/*n*/], int n) override |
64 | 4.29k | { |
65 | 4.29k | if (_pos >= _sz && n != 0) |
66 | 0 | throw IEX_NAMESPACE::InputExc ("Unexpected end of file."); |
67 | | |
68 | 4.29k | uint64_t n2 = n; |
69 | 4.29k | bool retVal = true; |
70 | | |
71 | 4.29k | if (_sz - _pos <= n2) |
72 | 3.61k | { |
73 | 3.61k | n2 = _sz - _pos; |
74 | 3.61k | retVal = false; |
75 | 3.61k | } |
76 | | |
77 | 4.29k | memcpy (c, _data + _pos, n2); |
78 | 4.29k | _pos += n2; |
79 | 4.29k | return retVal; |
80 | 4.29k | } |
81 | | |
82 | | char* readMemoryMapped (int n) override |
83 | 0 | { |
84 | 0 | if (_pos >= _sz) |
85 | 0 | throw IEX_NAMESPACE::InputExc ("Unexpected end of file."); |
86 | | |
87 | 0 | if (_pos + n > _sz) |
88 | 0 | throw IEX_NAMESPACE::InputExc ("Reading past end of file."); |
89 | | |
90 | 0 | char* retVal = _data + _pos; |
91 | 0 | _pos += n; |
92 | 0 | return retVal; |
93 | 0 | } |
94 | 0 | uint64_t tellg () override { return _pos; } |
95 | 0 | void seekg (uint64_t pos) override { _pos = pos; } |
96 | 0 | void clear () override {} |
97 | | |
98 | | private: |
99 | | char* _data; |
100 | | uint64_t _sz; |
101 | | uint64_t _pos; |
102 | | }; |
103 | | |
104 | | } // namespace |
105 | | |
106 | | //////////////////////////////////////// |
107 | | |
108 | | Context::Context () |
109 | 32.5k | : _ctxt (new exr_context_t(), [] (exr_context_t* todel) { |
110 | 32.5k | exr_finish (todel); |
111 | 32.5k | delete todel; |
112 | 32.5k | }) |
113 | 32.5k | { |
114 | 32.5k | } |
115 | | |
116 | | //////////////////////////////////////// |
117 | | |
118 | | Context::Context (const char* filename, const ContextInitializer& ctxtinit, read_mode_t) |
119 | 3.73k | : Context() |
120 | 3.73k | { |
121 | 3.73k | exr_result_t rv; |
122 | | |
123 | 3.73k | rv = exr_start_read (_ctxt.get (), filename, &(ctxtinit._initializer)); |
124 | 3.73k | if (EXR_ERR_SUCCESS != rv) |
125 | 762 | { |
126 | 762 | if (rv == EXR_ERR_MISSING_REQ_ATTR) |
127 | 209 | { |
128 | 209 | THROW ( |
129 | 209 | IEX_NAMESPACE::ArgExc, |
130 | 209 | "Invalid or missing attribute when attempting to open '" |
131 | 209 | << filename << "' for read"); |
132 | 209 | } |
133 | 553 | else |
134 | 553 | { |
135 | 553 | THROW ( |
136 | 553 | IEX_NAMESPACE::InputExc, |
137 | 553 | "Unable to open '" << filename << "' for read"); |
138 | 553 | } |
139 | 762 | } |
140 | 3.73k | } |
141 | | |
142 | | //////////////////////////////////////// |
143 | | |
144 | | Context::Context (const char* filename, const ContextInitializer& ctxtinit, temp_mode_t) |
145 | 0 | : Context() |
146 | 0 | { |
147 | 0 | if (EXR_ERR_SUCCESS != exr_start_temporary_context ( |
148 | 0 | _ctxt.get (), |
149 | 0 | filename, |
150 | 0 | &(ctxtinit._initializer))) |
151 | 0 | { |
152 | 0 | THROW ( |
153 | 0 | IEX_NAMESPACE::InputExc, |
154 | 0 | "Unable to create a temporary context"); |
155 | 0 | } |
156 | 0 | } |
157 | | |
158 | | //////////////////////////////////////// |
159 | | |
160 | | Context::Context (const char* filename, const ContextInitializer& ctxtinit, write_mode_t) |
161 | 0 | : Context() |
162 | 0 | { |
163 | 0 | if (EXR_ERR_SUCCESS != exr_start_write ( |
164 | 0 | _ctxt.get (), |
165 | 0 | filename, |
166 | 0 | EXR_WRITE_FILE_DIRECTLY, |
167 | 0 | &(ctxtinit._initializer))) |
168 | 0 | { |
169 | 0 | THROW ( |
170 | 0 | IEX_NAMESPACE::InputExc, |
171 | 0 | "Unable to open '" << filename << "' for write"); |
172 | 0 | } |
173 | 0 | } |
174 | | |
175 | | //////////////////////////////////////// |
176 | | |
177 | | void |
178 | | Context::setLongNameSupport (bool onoff) |
179 | 0 | { |
180 | 0 | if (EXR_ERR_SUCCESS != exr_set_longname_support (*_ctxt, onoff ? 1 : 0)) |
181 | 0 | { |
182 | 0 | THROW (IEX_NAMESPACE::ArgExc, "Unable to set long name support flag"); |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | //////////////////////////////////////// |
187 | | |
188 | | const char* |
189 | | Context::fileName () const |
190 | 542 | { |
191 | 542 | const char* filename = nullptr; |
192 | | |
193 | 542 | if (EXR_ERR_SUCCESS != exr_get_file_name (*_ctxt, &filename)) |
194 | 0 | { |
195 | 0 | THROW (IEX_NAMESPACE::ArgExc, "Unable to get filename from context"); |
196 | 0 | } |
197 | | |
198 | 542 | return filename; |
199 | 542 | } |
200 | | |
201 | | //////////////////////////////////////// |
202 | | |
203 | | int |
204 | | Context::version () const |
205 | 5.99k | { |
206 | 5.99k | uint32_t ver = 0; |
207 | | |
208 | 5.99k | if (EXR_ERR_SUCCESS != exr_get_file_version_and_flags (*_ctxt, &ver)) |
209 | 0 | { |
210 | 0 | THROW ( |
211 | 0 | IEX_NAMESPACE::ArgExc, "Unable to get file version from context"); |
212 | 0 | } |
213 | | |
214 | 5.99k | return static_cast<int> (ver); |
215 | 5.99k | } |
216 | | |
217 | | //////////////////////////////////////// |
218 | | |
219 | | int |
220 | | Context::partCount () const |
221 | 2.97k | { |
222 | 2.97k | int count = 0; |
223 | | |
224 | 2.97k | if (EXR_ERR_SUCCESS != exr_get_count (*_ctxt, &count)) |
225 | 0 | { |
226 | 0 | THROW ( |
227 | 0 | IEX_NAMESPACE::ArgExc, |
228 | 0 | "Unable to get part count for file '" << fileName () << "'"); |
229 | 0 | } |
230 | | |
231 | 2.97k | return count; |
232 | 2.97k | } |
233 | | |
234 | | //////////////////////////////////////// |
235 | | |
236 | | exr_storage_t |
237 | | Context::storage (int partidx) const |
238 | 5.69k | { |
239 | 5.69k | exr_storage_t storage = EXR_STORAGE_LAST_TYPE; |
240 | | |
241 | 5.69k | if (EXR_ERR_SUCCESS != exr_get_storage (*_ctxt, partidx, &storage)) |
242 | 0 | { |
243 | 0 | THROW ( |
244 | 0 | IEX_NAMESPACE::ArgExc, |
245 | 0 | "Unable to get storage type for part " << partidx << " in file '" |
246 | 0 | << fileName () << "'"); |
247 | 0 | } |
248 | | |
249 | 5.69k | return storage; |
250 | 5.69k | } |
251 | | |
252 | | //////////////////////////////////////// |
253 | | |
254 | | exr_attr_box2i_t |
255 | | Context::dataWindow (int partidx) const |
256 | 63.3k | { |
257 | 63.3k | exr_attr_box2i_t dw; |
258 | | |
259 | 63.3k | if (EXR_ERR_SUCCESS != exr_get_data_window (*_ctxt, partidx, &dw)) |
260 | 0 | { |
261 | 0 | THROW ( |
262 | 0 | IEX_NAMESPACE::ArgExc, |
263 | 0 | "Unable to get the data window for part " << partidx << " in file '" |
264 | 0 | << fileName () << "'"); |
265 | 0 | } |
266 | | |
267 | 63.3k | return dw; |
268 | 63.3k | } |
269 | | |
270 | | //////////////////////////////////////// |
271 | | |
272 | | const exr_attr_chlist_t* |
273 | | Context::channels (int partidx) const |
274 | 11.8k | { |
275 | 11.8k | const exr_attr_chlist_t* cl; |
276 | | |
277 | 11.8k | if (EXR_ERR_SUCCESS != exr_get_channels (*_ctxt, partidx, &cl)) |
278 | 0 | { |
279 | 0 | THROW ( |
280 | 0 | IEX_NAMESPACE::ArgExc, |
281 | 0 | "Unable to get the channel list for part " |
282 | 0 | << partidx << " in file '" << fileName () << "'"); |
283 | 0 | } |
284 | | |
285 | 11.8k | return cl; |
286 | 11.8k | } |
287 | | |
288 | | //////////////////////////////////////// |
289 | | |
290 | | bool |
291 | | Context::hasChannel (int partidx, const char* name) const |
292 | 492 | { |
293 | 492 | return findChannel (partidx, name) != nullptr; |
294 | 492 | } |
295 | | |
296 | | const exr_attr_chlist_entry_t* Context::findChannel (int partidx, const char* name) const |
297 | 11.8k | { |
298 | 11.8k | const exr_attr_chlist_t* cl = channels (partidx); |
299 | 11.8k | int32_t len = strlen (name); |
300 | | |
301 | 65.9k | for (int i = 0; i < cl->num_channels; ++i) |
302 | 59.3k | { |
303 | 59.3k | const exr_attr_chlist_entry_t* curc = cl->entries + i; |
304 | 59.3k | if (curc->name.length == len && 0 == memcmp (name, curc->name.str, len)) |
305 | 5.18k | { |
306 | 5.18k | return curc; |
307 | 5.18k | } |
308 | 59.3k | } |
309 | 6.64k | return nullptr; |
310 | 11.8k | } |
311 | | |
312 | | //////////////////////////////////////// |
313 | | |
314 | | exr_lineorder_t |
315 | | Context::lineOrder (int partidx) const |
316 | 0 | { |
317 | 0 | exr_lineorder_t lo; |
318 | |
|
319 | 0 | if (EXR_ERR_SUCCESS != exr_get_lineorder (*_ctxt, partidx, &lo)) |
320 | 0 | { |
321 | 0 | THROW ( |
322 | 0 | IEX_NAMESPACE::ArgExc, |
323 | 0 | "Unable to get the line order for part " << partidx << " in file '" |
324 | 0 | << fileName () << "'"); |
325 | 0 | } |
326 | | |
327 | 0 | return lo; |
328 | 0 | } |
329 | | |
330 | | //////////////////////////////////////// |
331 | | |
332 | | int |
333 | | Context::attrCount (int partidx) const |
334 | 0 | { |
335 | 0 | int32_t attrcnt = 0; |
336 | |
|
337 | 0 | if (EXR_ERR_SUCCESS != exr_get_attribute_count (*_ctxt, partidx, &attrcnt)) |
338 | 0 | { |
339 | 0 | THROW ( |
340 | 0 | IEX_NAMESPACE::ArgExc, |
341 | 0 | "Unable to get attribute for part " << partidx << " in file '" |
342 | 0 | << fileName () << "'"); |
343 | 0 | } |
344 | | |
345 | 0 | return 0; |
346 | 0 | } |
347 | | |
348 | | //////////////////////////////////////// |
349 | | |
350 | | const exr_attribute_t* |
351 | | Context::getAttr (int partidx, int attridx) const |
352 | 0 | { |
353 | 0 | const exr_attribute_t* attr = nullptr; |
354 | |
|
355 | 0 | if (EXR_ERR_SUCCESS != |
356 | 0 | exr_get_attribute_by_index ( |
357 | 0 | *_ctxt, partidx, EXR_ATTR_LIST_FILE_ORDER, attridx, &attr)) |
358 | 0 | { |
359 | 0 | THROW ( |
360 | 0 | IEX_NAMESPACE::ArgExc, |
361 | 0 | "Unable to get attribute index " << attridx << " for part " |
362 | 0 | << partidx << " in file '" |
363 | 0 | << fileName () << "'"); |
364 | 0 | } |
365 | | |
366 | 0 | return attr; |
367 | 0 | } |
368 | | |
369 | | //////////////////////////////////////// |
370 | | |
371 | | const exr_attribute_t* |
372 | | Context::getAttr (int partidx, const char* name) const |
373 | 0 | { |
374 | 0 | const exr_attribute_t* attr = nullptr; |
375 | 0 | exr_result_t res; |
376 | |
|
377 | 0 | res = exr_get_attribute_by_name (*_ctxt, partidx, name, &attr); |
378 | |
|
379 | 0 | if (res == EXR_ERR_SUCCESS || res == EXR_ERR_NO_ATTR_BY_NAME) return attr; |
380 | | |
381 | 0 | THROW ( |
382 | 0 | IEX_NAMESPACE::ArgExc, |
383 | 0 | "Unable to find attribute '" << name << "' for part " << partidx |
384 | 0 | << " in file '" << fileName () << "'"); |
385 | 0 | } |
386 | | |
387 | | //////////////////////////////////////// |
388 | | |
389 | | Header |
390 | | Context::header (int partidx) const |
391 | 29.4k | { |
392 | 29.4k | Header hdr; |
393 | 29.4k | int32_t attrcnt = 0; |
394 | 29.4k | const exr_attribute_t* cur = nullptr; |
395 | | |
396 | 29.4k | if (EXR_ERR_SUCCESS != exr_get_attribute_count (*_ctxt, partidx, &attrcnt)) |
397 | 0 | { |
398 | 0 | THROW ( |
399 | 0 | IEX_NAMESPACE::ArgExc, |
400 | 0 | "Unable to get attribute for part " << partidx << " in file '" |
401 | 0 | << fileName () << "'"); |
402 | 0 | } |
403 | | |
404 | 469k | for (int32_t idx = 0; idx < attrcnt; ++idx) |
405 | 440k | { |
406 | 440k | if (EXR_ERR_SUCCESS != |
407 | 440k | exr_get_attribute_by_index ( |
408 | 440k | *_ctxt, partidx, EXR_ATTR_LIST_FILE_ORDER, idx, &cur)) |
409 | 0 | { |
410 | 0 | THROW ( |
411 | 0 | IEX_NAMESPACE::ArgExc, |
412 | 0 | "Unable to get attribute index " << idx << " for part " |
413 | 0 | << partidx << " in file '" |
414 | 0 | << fileName () << "'"); |
415 | 0 | } |
416 | | |
417 | 440k | switch (cur->type) |
418 | 440k | { |
419 | 22.2k | case EXR_ATTR_INT: |
420 | 22.2k | hdr.insert (cur->name, IntAttribute (cur->i)); |
421 | 22.2k | break; |
422 | 361 | case EXR_ATTR_DOUBLE: |
423 | 361 | hdr.insert (cur->name, DoubleAttribute (cur->d)); |
424 | 361 | break; |
425 | 68.2k | case EXR_ATTR_FLOAT: |
426 | 68.2k | hdr.insert (cur->name, FloatAttribute (cur->f)); |
427 | 68.2k | break; |
428 | | |
429 | 74.4k | case EXR_ATTR_BOX2I: |
430 | 74.4k | hdr.insert ( |
431 | 74.4k | cur->name, |
432 | 74.4k | Box2iAttribute (IMATH_NAMESPACE::Box2i ( |
433 | 74.4k | IMATH_NAMESPACE::V2i (cur->box2i->min), |
434 | 74.4k | IMATH_NAMESPACE::V2i (cur->box2i->max)))); |
435 | 74.4k | break; |
436 | 117 | case EXR_ATTR_BOX2F: |
437 | 117 | hdr.insert ( |
438 | 117 | cur->name, |
439 | 117 | Box2fAttribute (IMATH_NAMESPACE::Box2f ( |
440 | 117 | IMATH_NAMESPACE::V2f (cur->box2f->min), |
441 | 117 | IMATH_NAMESPACE::V2f (cur->box2f->max)))); |
442 | 117 | break; |
443 | | |
444 | 451 | case EXR_ATTR_V2I: |
445 | 451 | hdr.insert ( |
446 | 451 | cur->name, |
447 | 451 | V2iAttribute (IMATH_NAMESPACE::V2i (*(cur->v2i)))); |
448 | 451 | break; |
449 | 29.6k | case EXR_ATTR_V2F: |
450 | 29.6k | hdr.insert ( |
451 | 29.6k | cur->name, |
452 | 29.6k | V2fAttribute (IMATH_NAMESPACE::V2f (*(cur->v2f)))); |
453 | 29.6k | break; |
454 | 257 | case EXR_ATTR_V2D: |
455 | 257 | hdr.insert ( |
456 | 257 | cur->name, |
457 | 257 | V2dAttribute (IMATH_NAMESPACE::V2d (*(cur->v2d)))); |
458 | 257 | break; |
459 | 657 | case EXR_ATTR_V3I: |
460 | 657 | hdr.insert ( |
461 | 657 | cur->name, |
462 | 657 | V3iAttribute (IMATH_NAMESPACE::V3i (*(cur->v3i)))); |
463 | 657 | break; |
464 | 2.75k | case EXR_ATTR_V3F: |
465 | 2.75k | hdr.insert ( |
466 | 2.75k | cur->name, |
467 | 2.75k | V3fAttribute (IMATH_NAMESPACE::V3f (*(cur->v3f)))); |
468 | 2.75k | break; |
469 | 196 | case EXR_ATTR_V3D: |
470 | 196 | hdr.insert ( |
471 | 196 | cur->name, |
472 | 196 | V3dAttribute (IMATH_NAMESPACE::V3d (*(cur->v3d)))); |
473 | 196 | break; |
474 | | |
475 | 76.6k | case EXR_ATTR_STRING: |
476 | 76.6k | hdr.insert ( |
477 | 76.6k | cur->name, |
478 | 76.6k | StringAttribute ( |
479 | 76.6k | std::string (cur->string->str, cur->string->length))); |
480 | 76.6k | break; |
481 | | |
482 | 32.7k | case EXR_ATTR_COMPRESSION: |
483 | 32.7k | hdr.insert ( |
484 | 32.7k | cur->name, CompressionAttribute (Compression (cur->uc))); |
485 | 32.7k | break; |
486 | 33 | case EXR_ATTR_ENVMAP: |
487 | 33 | hdr.insert (cur->name, EnvmapAttribute (Envmap (cur->uc))); |
488 | 33 | break; |
489 | 29.6k | case EXR_ATTR_LINEORDER: |
490 | 29.6k | hdr.insert ( |
491 | 29.6k | cur->name, LineOrderAttribute (LineOrder (cur->uc))); |
492 | 29.6k | break; |
493 | | |
494 | 34.6k | case EXR_ATTR_CHLIST: { |
495 | 34.6k | ChannelList& chans = hdr.channels (); |
496 | | |
497 | 100k | for (int c = 0; c < cur->chlist->num_channels; ++c) |
498 | 66.2k | { |
499 | 66.2k | const exr_attr_chlist_entry_t& curc = |
500 | 66.2k | cur->chlist->entries[c]; |
501 | 66.2k | chans.insert ( |
502 | 66.2k | curc.name.str, |
503 | 66.2k | Channel ( |
504 | 66.2k | PixelType (curc.pixel_type), |
505 | 66.2k | curc.x_sampling, |
506 | 66.2k | curc.y_sampling, |
507 | 66.2k | curc.p_linear != 0)); |
508 | 66.2k | } |
509 | 34.6k | break; |
510 | 0 | } |
511 | | |
512 | 9.10k | case EXR_ATTR_TILEDESC: |
513 | 9.10k | hdr.insert ( |
514 | 9.10k | cur->name, TileDescriptionAttribute ( |
515 | 9.10k | TileDescription ( |
516 | 9.10k | cur->tiledesc->x_size, |
517 | 9.10k | cur->tiledesc->y_size, |
518 | 9.10k | (LevelMode)(EXR_GET_TILE_LEVEL_MODE (*cur->tiledesc)), |
519 | 9.10k | (LevelRoundingMode)(EXR_GET_TILE_ROUND_MODE (*cur->tiledesc))))); |
520 | 9.10k | break; |
521 | | |
522 | 1.06k | case EXR_ATTR_FLOAT_VECTOR: |
523 | 1.06k | hdr.insert ( |
524 | 1.06k | cur->name, FloatVectorAttribute ( |
525 | 1.06k | FloatVector ( |
526 | 1.06k | cur->floatvector->arr, |
527 | 1.06k | cur->floatvector->arr + cur->floatvector->length))); |
528 | 1.06k | break; |
529 | | |
530 | 467 | case EXR_ATTR_M33F: |
531 | 467 | hdr.insert ( |
532 | 467 | cur->name, M33fAttribute ( |
533 | 467 | IMATH_NAMESPACE::M33f ( |
534 | 467 | *reinterpret_cast<float (*)[3][3]> (cur->m33f->m)))); |
535 | 467 | break; |
536 | 8 | case EXR_ATTR_M33D: |
537 | 8 | hdr.insert ( |
538 | 8 | cur->name, M33dAttribute ( |
539 | 8 | IMATH_NAMESPACE::M33d ( |
540 | 8 | *reinterpret_cast<double (*)[3][3]> (cur->m33d->m)))); |
541 | 8 | break; |
542 | 0 | case EXR_ATTR_M44F: |
543 | 0 | hdr.insert ( |
544 | 0 | cur->name, M44fAttribute ( |
545 | 0 | IMATH_NAMESPACE::M44f ( |
546 | 0 | *reinterpret_cast<float (*)[4][4]> (cur->m44f->m)))); |
547 | 0 | break; |
548 | 37 | case EXR_ATTR_M44D: |
549 | 37 | hdr.insert ( |
550 | 37 | cur->name, M44dAttribute ( |
551 | 37 | IMATH_NAMESPACE::M44d ( |
552 | 37 | *reinterpret_cast<double (*)[4][4]> (cur->m44d->m)))); |
553 | 37 | break; |
554 | | |
555 | 4.81k | case EXR_ATTR_CHROMATICITIES: |
556 | 4.81k | hdr.insert ( |
557 | 4.81k | cur->name, ChromaticitiesAttribute ( |
558 | 4.81k | Chromaticities ( |
559 | 4.81k | IMATH_NAMESPACE::V2f ( |
560 | 4.81k | cur->chromaticities->red_x, |
561 | 4.81k | cur->chromaticities->red_y), |
562 | 4.81k | IMATH_NAMESPACE::V2f ( |
563 | 4.81k | cur->chromaticities->green_x, |
564 | 4.81k | cur->chromaticities->green_y), |
565 | 4.81k | IMATH_NAMESPACE::V2f ( |
566 | 4.81k | cur->chromaticities->blue_x, |
567 | 4.81k | cur->chromaticities->blue_y), |
568 | 4.81k | IMATH_NAMESPACE::V2f ( |
569 | 4.81k | cur->chromaticities->white_x, |
570 | 4.81k | cur->chromaticities->white_y)))); |
571 | 4.81k | break; |
572 | 0 | case EXR_ATTR_KEYCODE: |
573 | 0 | hdr.insert ( |
574 | 0 | cur->name, KeyCodeAttribute ( |
575 | 0 | KeyCode ( |
576 | 0 | cur->keycode->film_mfc_code, |
577 | 0 | cur->keycode->film_type, |
578 | 0 | cur->keycode->prefix, |
579 | 0 | cur->keycode->count, |
580 | 0 | cur->keycode->perf_offset, |
581 | 0 | cur->keycode->perfs_per_frame, |
582 | 0 | cur->keycode->perfs_per_count))); |
583 | 0 | break; |
584 | 343 | case EXR_ATTR_RATIONAL: |
585 | 343 | hdr.insert ( |
586 | 343 | cur->name, RationalAttribute ( |
587 | 343 | Rational ( |
588 | 343 | cur->rational->num, |
589 | 343 | cur->rational->denom))); |
590 | 343 | break; |
591 | 0 | case EXR_ATTR_TIMECODE: |
592 | 0 | hdr.insert ( |
593 | 0 | cur->name, TimeCodeAttribute ( |
594 | 0 | TimeCode ( |
595 | 0 | cur->timecode->time_and_flags, |
596 | 0 | cur->timecode->user_data))); |
597 | 0 | break; |
598 | 442 | case EXR_ATTR_PREVIEW: |
599 | 442 | hdr.insert ( |
600 | 442 | cur->name, PreviewImageAttribute ( |
601 | 442 | PreviewImage ( |
602 | 442 | cur->preview->width, |
603 | 442 | cur->preview->height, |
604 | 442 | reinterpret_cast<const PreviewRgba*> (cur->preview->rgba)))); |
605 | 442 | break; |
606 | 1.46k | case EXR_ATTR_STRING_VECTOR: |
607 | 1.46k | { |
608 | 1.46k | std::vector<std::string> svec; |
609 | 1.46k | svec.resize (cur->stringvector->n_strings); |
610 | 2.92k | for (int s = 0; s < cur->stringvector->n_strings; ++s) |
611 | 1.45k | { |
612 | 1.45k | svec[s] = std::string ( |
613 | 1.45k | cur->stringvector->strings[s].str, |
614 | 1.45k | cur->stringvector->strings[s].length); |
615 | 1.45k | } |
616 | 1.46k | hdr.insert ( |
617 | 1.46k | cur->name, StringVectorAttribute (svec)); |
618 | 1.46k | break; |
619 | 0 | } |
620 | | |
621 | 122 | case EXR_ATTR_DEEP_IMAGE_STATE: |
622 | 122 | hdr.insert ( |
623 | 122 | cur->name, DeepImageStateAttribute (DeepImageState (cur->uc))); |
624 | 122 | break; |
625 | | |
626 | 49.4k | case EXR_ATTR_OPAQUE: |
627 | 49.4k | if (Attribute::knownType (cur->type_name)) |
628 | 2.16k | { |
629 | 2.16k | MemAttrStream mas {cur->opaque}; |
630 | | |
631 | 2.16k | std::unique_ptr<Attribute> attr; |
632 | 2.16k | attr.reset (Attribute::newAttribute (cur->type_name)); |
633 | | |
634 | 2.16k | attr->readValueFrom (mas, cur->opaque->size, version ()); |
635 | | // TODO: can we avoid a double copy? |
636 | 2.16k | hdr.insert (cur->name, *attr); |
637 | 2.16k | } |
638 | 47.2k | else |
639 | 47.2k | { |
640 | 47.2k | hdr.insert ( |
641 | 47.2k | cur->name, OpaqueAttribute ( |
642 | 47.2k | cur->type_name, |
643 | 47.2k | cur->opaque->size, |
644 | 47.2k | cur->opaque->packed_data)); |
645 | 47.2k | } |
646 | 49.4k | break; |
647 | | |
648 | 0 | case EXR_ATTR_UNKNOWN: |
649 | 0 | case EXR_ATTR_LAST_KNOWN_TYPE: |
650 | 0 | default: { |
651 | 0 | THROW (IEX_NAMESPACE::LogicExc, |
652 | 0 | "Unknown attribute '" |
653 | 0 | << cur->name |
654 | 0 | << "' of type '" |
655 | 0 | << cur->type << "', conversion to legacy header not yet implemented"); |
656 | 0 | } |
657 | 440k | } |
658 | 440k | } |
659 | | |
660 | 29.4k | return hdr; |
661 | 29.4k | } |
662 | | |
663 | | //////////////////////////////////////// |
664 | | |
665 | | |
666 | | #define EXR_SET_ATTR(type, cpptype, attrval) \ |
667 | 0 | if (!strcmp (attrT, #type)) \ |
668 | 0 | { \ |
669 | 0 | const cpptype *attr = dynamic_cast<const cpptype*> (&a); \ |
670 | 0 | if (!attr) \ |
671 | 0 | throw IEX_NAMESPACE::ArgExc ("unexpected type mismatch"); \ |
672 | 0 | rv = exr_attr_set_##type (*_ctxt, partnum, i.name (), attrval); \ |
673 | 0 | if (rv != EXR_ERR_SUCCESS) \ |
674 | 0 | throw IEX_NAMESPACE::ArgExc ("Unable to copy attribute"); \ |
675 | 0 | continue; \ |
676 | 0 | } |
677 | | |
678 | | |
679 | | void Context::addHeader (int partnum, const Header &h) |
680 | 0 | { |
681 | 0 | exr_result_t rv; |
682 | | // TODO: ImfHeader iterator types should support operator* so they can |
683 | | // use ranged-based for |
684 | 0 | for (auto i = h.begin (); i != h.end (); ++i) |
685 | 0 | { |
686 | 0 | const Attribute& a = i.attribute (); |
687 | 0 | const char* attrT = a.typeName (); |
688 | |
|
689 | 0 | if (!strcmp (i.name (), "channels")) |
690 | 0 | { |
691 | 0 | const ChannelList& chans = h.channels (); |
692 | |
|
693 | 0 | for (auto c = chans.begin (); c != chans.end (); ++c) |
694 | 0 | { |
695 | 0 | const Channel &cdef = c.channel (); |
696 | 0 | rv = exr_add_channel ( |
697 | 0 | *_ctxt, partnum, c.name (), |
698 | 0 | (exr_pixel_type_t)cdef.type, |
699 | 0 | cdef.pLinear ? EXR_PERCEPTUALLY_LINEAR : EXR_PERCEPTUALLY_LOGARITHMIC, |
700 | 0 | cdef.xSampling, |
701 | 0 | cdef.ySampling); |
702 | 0 | if (rv != EXR_ERR_SUCCESS) |
703 | 0 | throw IEX_NAMESPACE::ArgExc ("Unable to copy channel information"); |
704 | 0 | } |
705 | 0 | continue; |
706 | 0 | } |
707 | | |
708 | 0 | if (!strcmp (i.name (), "lineOrder")) |
709 | 0 | { |
710 | 0 | const LineOrderAttribute *attr = |
711 | 0 | dynamic_cast<const LineOrderAttribute*> (&a); |
712 | 0 | if (!attr) |
713 | 0 | throw IEX_NAMESPACE::ArgExc ("unexpected type mismatch"); |
714 | 0 | rv = exr_set_lineorder ( |
715 | 0 | *_ctxt, partnum, (exr_lineorder_t)attr->value ()); |
716 | 0 | if (rv != EXR_ERR_SUCCESS) |
717 | 0 | throw IEX_NAMESPACE::ArgExc ("Unable to copy attribute"); |
718 | 0 | continue; |
719 | 0 | } |
720 | | |
721 | 0 | if (!strcmp (attrT, "tiledesc")) |
722 | 0 | { |
723 | 0 | const TileDescriptionAttribute *attr = |
724 | 0 | dynamic_cast<const TileDescriptionAttribute*> (&a); |
725 | 0 | if (!attr) |
726 | 0 | throw IEX_NAMESPACE::ArgExc ("unexpected type mismatch"); |
727 | 0 | TileDescription td = attr->value (); |
728 | |
|
729 | 0 | rv = exr_set_tile_descriptor ( |
730 | 0 | *_ctxt, partnum, |
731 | 0 | td.xSize, |
732 | 0 | td.ySize, |
733 | 0 | (exr_tile_level_mode_t)td.mode, |
734 | 0 | (exr_tile_round_mode_t)td.roundingMode); |
735 | |
|
736 | 0 | if (rv != EXR_ERR_SUCCESS) |
737 | 0 | throw IEX_NAMESPACE::ArgExc ("Unable to copy attribute"); |
738 | 0 | continue; |
739 | 0 | } |
740 | | |
741 | 0 | EXR_SET_ATTR(string, StringAttribute, attr->value ().c_str ()); |
742 | 0 | EXR_SET_ATTR(int, IntAttribute, attr->value ()); |
743 | 0 | EXR_SET_ATTR(float, FloatAttribute, attr->value ()); |
744 | 0 | EXR_SET_ATTR(double, DoubleAttribute, attr->value ()); |
745 | 0 | EXR_SET_ATTR(compression, CompressionAttribute, (exr_compression_t)attr->value ()); |
746 | 0 | EXR_SET_ATTR(envmap, EnvmapAttribute, (exr_envmap_t)attr->value ()); |
747 | 0 | EXR_SET_ATTR(v2i, V2iAttribute, |
748 | 0 | reinterpret_cast<const exr_attr_v2i_t*>(&(attr->value ()))); |
749 | 0 | EXR_SET_ATTR(v2f, V2fAttribute, |
750 | 0 | reinterpret_cast<const exr_attr_v2f_t*>(&(attr->value ()))); |
751 | 0 | EXR_SET_ATTR(v2d, V2dAttribute, |
752 | 0 | reinterpret_cast<const exr_attr_v2d_t*>(&(attr->value ()))); |
753 | 0 | EXR_SET_ATTR(v3i, V3iAttribute, |
754 | 0 | reinterpret_cast<const exr_attr_v3i_t*>(&(attr->value ()))); |
755 | 0 | EXR_SET_ATTR(v3f, V3fAttribute, |
756 | 0 | reinterpret_cast<const exr_attr_v3f_t*>(&(attr->value ()))); |
757 | 0 | EXR_SET_ATTR(v3d, V3dAttribute, |
758 | 0 | reinterpret_cast<const exr_attr_v3d_t*>(&(attr->value ()))); |
759 | 0 | EXR_SET_ATTR(m33f, M33fAttribute, |
760 | 0 | reinterpret_cast<const exr_attr_m33f_t*>(&(attr->value ()))); |
761 | 0 | EXR_SET_ATTR(m33d, M33dAttribute, |
762 | 0 | reinterpret_cast<const exr_attr_m33d_t*>(&(attr->value ()))); |
763 | 0 | EXR_SET_ATTR(m44f, M44fAttribute, |
764 | 0 | reinterpret_cast<const exr_attr_m44f_t*>(&(attr->value ()))); |
765 | 0 | EXR_SET_ATTR(m44d, M44dAttribute, |
766 | 0 | reinterpret_cast<const exr_attr_m44d_t*>(&(attr->value ()))); |
767 | 0 | EXR_SET_ATTR(box2i, Box2iAttribute, |
768 | 0 | reinterpret_cast<const exr_attr_box2i_t*>(&(attr->value ()))); |
769 | 0 | EXR_SET_ATTR(box2f, Box2fAttribute, |
770 | 0 | reinterpret_cast<const exr_attr_box2f_t*>(&(attr->value ()))); |
771 | |
|
772 | 0 | if (!strcmp (attrT, "chromaticities")) |
773 | 0 | { |
774 | 0 | const ChromaticitiesAttribute *attr = |
775 | 0 | dynamic_cast<const ChromaticitiesAttribute*> (&a); |
776 | 0 | if (!attr) |
777 | 0 | throw IEX_NAMESPACE::ArgExc ("unexpected type mismatch"); |
778 | 0 | Chromaticities ac = attr->value (); |
779 | 0 | exr_attr_chromaticities_t cac; |
780 | |
|
781 | 0 | cac.red_x = ac.red.x; |
782 | 0 | cac.red_y = ac.red.y; |
783 | 0 | cac.green_x = ac.green.x; |
784 | 0 | cac.green_y = ac.green.y; |
785 | 0 | cac.blue_x = ac.blue.x; |
786 | 0 | cac.blue_y = ac.blue.y; |
787 | 0 | cac.white_x = ac.white.x; |
788 | 0 | cac.white_y = ac.white.y; |
789 | |
|
790 | 0 | rv = exr_attr_set_chromaticities ( |
791 | 0 | *_ctxt, partnum, i.name (), &cac); |
792 | |
|
793 | 0 | if (rv != EXR_ERR_SUCCESS) |
794 | 0 | throw IEX_NAMESPACE::ArgExc ("Unable to copy attribute"); |
795 | 0 | continue; |
796 | 0 | } |
797 | | |
798 | 0 | if (!strcmp (attrT, "stringvector")) |
799 | 0 | { |
800 | 0 | continue; |
801 | 0 | } |
802 | | |
803 | 0 | if (!strcmp (attrT, "floatvector")) |
804 | 0 | { |
805 | 0 | continue; |
806 | 0 | } |
807 | | |
808 | 0 | if (!strcmp (attrT, "preview")) |
809 | 0 | { |
810 | 0 | continue; |
811 | 0 | } |
812 | | |
813 | 0 | if (!strcmp (attrT, "rational")) |
814 | 0 | { |
815 | 0 | continue; |
816 | 0 | } |
817 | | |
818 | 0 | if (!strcmp (attrT, "timecode")) |
819 | 0 | { |
820 | 0 | continue; |
821 | 0 | } |
822 | | |
823 | 0 | if (!strcmp (attrT, "keycode")) |
824 | 0 | { |
825 | 0 | continue; |
826 | 0 | } |
827 | | |
828 | 0 | if (!strcmp (attrT, "deepImageState")) |
829 | 0 | { |
830 | 0 | continue; |
831 | 0 | } |
832 | | |
833 | | //THROW ( |
834 | | // IEX_NAMESPACE::LogicExc, |
835 | | // "Conversion of attribute '" << i.name () << "' of type '" << attrT |
836 | | // << "' to core value not yet implemented"); |
837 | 0 | } |
838 | 0 | } |
839 | | |
840 | | //////////////////////////////////////// |
841 | | |
842 | | bool |
843 | | Context::chunkTableValid (int partidx) const |
844 | 374 | { |
845 | 374 | return exr_validate_chunk_table (*_ctxt, partidx) == EXR_ERR_SUCCESS; |
846 | 374 | } |
847 | | |
848 | | OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT |