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