Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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