Coverage Report

Created: 2025-07-16 07:53

/usr/local/include/OpenEXR/ImfHeader.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// SPDX-License-Identifier: BSD-3-Clause
3
// Copyright (c) Contributors to the OpenEXR Project.
4
//
5
6
#ifndef INCLUDED_IMF_HEADER_H
7
#define INCLUDED_IMF_HEADER_H
8
9
//-----------------------------------------------------------------------------
10
//
11
//  class Header
12
//
13
//-----------------------------------------------------------------------------
14
15
#include "ImfForward.h"
16
17
#include "IexBaseExc.h"
18
#include "ImathBox.h"
19
#include "ImathVec.h"
20
#include "ImfCompression.h"
21
#include "ImfLineOrder.h"
22
#include "ImfName.h"
23
#include "ImfTileDescription.h"
24
25
#include "ImfAttribute.h"
26
27
#include <cstdint>
28
#include <iosfwd>
29
#include <map>
30
#include <string>
31
32
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
33
34
using std::string;
35
36
class IMF_EXPORT_TYPE Header
37
{
38
public:
39
    //----------------------------------------------------------------
40
    // Default constructor -- the display window and the data window
41
    // are both set to Box2i (V2i (0, 0), V2i (width-1, height-1).
42
    //----------------------------------------------------------------
43
44
    IMF_EXPORT
45
    Header (
46
        int                         width            = 64,
47
        int                         height           = 64,
48
        float                       pixelAspectRatio = 1,
49
        const IMATH_NAMESPACE::V2f& screenWindowCenter =
50
            IMATH_NAMESPACE::V2f (0, 0),
51
        float     screenWindowWidth = 1,
52
        LineOrder lineOrder         = INCREASING_Y,
53
        Compression                 = ZIP_COMPRESSION);
54
55
    //--------------------------------------------------------------------
56
    // Constructor -- the data window is specified explicitly; the display
57
    // window is set to Box2i (V2i (0, 0), V2i (width-1, height-1).
58
    //--------------------------------------------------------------------
59
60
    IMF_EXPORT
61
    Header (
62
        int                           width,
63
        int                           height,
64
        const IMATH_NAMESPACE::Box2i& dataWindow,
65
        float                         pixelAspectRatio = 1,
66
        const IMATH_NAMESPACE::V2f&   screenWindowCenter =
67
            IMATH_NAMESPACE::V2f (0, 0),
68
        float     screenWindowWidth = 1,
69
        LineOrder lineOrder         = INCREASING_Y,
70
        Compression                 = ZIP_COMPRESSION);
71
72
    //----------------------------------------------------------
73
    // Constructor -- the display window and the data window are
74
    // both specified explicitly.
75
    //----------------------------------------------------------
76
77
    IMF_EXPORT
78
    Header (
79
        const IMATH_NAMESPACE::Box2i& displayWindow,
80
        const IMATH_NAMESPACE::Box2i& dataWindow,
81
        float                         pixelAspectRatio = 1,
82
        const IMATH_NAMESPACE::V2f&   screenWindowCenter =
83
            IMATH_NAMESPACE::V2f (0, 0),
84
        float     screenWindowWidth = 1,
85
        LineOrder lineOrder         = INCREASING_Y,
86
        Compression                 = ZIP_COMPRESSION);
87
88
    //-----------------
89
    // Copy constructor
90
    //-----------------
91
92
    IMF_EXPORT
93
    Header (const Header& other);
94
    IMF_EXPORT
95
    Header (Header&& other);
96
97
    //-----------
98
    // Destructor
99
    //-----------
100
101
    IMF_EXPORT
102
    ~Header ();
103
104
    //-----------
105
    // Assignment
106
    //-----------
107
108
    IMF_EXPORT
109
    Header& operator= (const Header& other);
110
    IMF_EXPORT
111
    Header& operator= (Header&& other);
112
113
    //---------------------------------------------------------------
114
    // Add an attribute:
115
    //
116
    // insert(n,attr) If no attribute with name n exists, a new
117
    //      attribute with name n, and the same type as
118
    //      attr, is added, and the value of attr is
119
    //      copied into the new attribute.
120
    //
121
    //      If an attribute with name n exists, and its
122
    //      type is the same as attr, the value of attr
123
    //      is copied into this attribute.
124
    //
125
    //      If an attribute with name n exists, and its
126
    //      type is different from attr, an IEX_NAMESPACE::TypeExc
127
    //      is thrown.
128
    //
129
    //---------------------------------------------------------------
130
131
    IMF_EXPORT
132
    void insert (const char name[], const Attribute& attribute);
133
134
    IMF_EXPORT
135
    void insert (const std::string& name, const Attribute& attribute);
136
137
    //---------------------------------------------------------------
138
    // Remove an attribute:
139
    //
140
    // remove(n)       If an attribute with name n exists, then it
141
    //                 is removed from the map of present attributes.
142
    //
143
    //                 If no attribute with name n exists, then this
144
    //                 functions becomes a 'no-op'
145
    //
146
    //---------------------------------------------------------------
147
148
    IMF_EXPORT
149
    void erase (const char name[]);
150
    IMF_EXPORT
151
    void erase (const std::string& name);
152
153
    //------------------------------------------------------------------
154
    // Access to existing attributes:
155
    //
156
    // [n]      Returns a reference to the attribute
157
    //        with name n.  If no attribute with
158
    //        name n exists, an IEX_NAMESPACE::ArgExc is thrown.
159
    //
160
    // typedAttribute<T>(n) Returns a reference to the attribute
161
    //        with name n and type T.  If no attribute
162
    //        with name n exists, an IEX_NAMESPACE::ArgExc is
163
    //        thrown.  If an attribute with name n
164
    //        exists, but its type is not T, an
165
    //        IEX_NAMESPACE::TypeExc is thrown.
166
    //
167
    // findTypedAttribute<T>(n) Returns a pointer to the attribute with
168
    //        name n and type T, or 0 if no attribute
169
    //        with name n and type T exists.
170
    //
171
    //------------------------------------------------------------------
172
173
    IMF_EXPORT
174
    Attribute& operator[] (const char name[]);
175
    IMF_EXPORT
176
    const Attribute& operator[] (const char name[]) const;
177
178
    IMF_EXPORT
179
    Attribute& operator[] (const std::string& name);
180
    IMF_EXPORT
181
    const Attribute& operator[] (const std::string& name) const;
182
183
    template <class T> T&       typedAttribute (const char name[]);
184
    template <class T> const T& typedAttribute (const char name[]) const;
185
186
    template <class T> T&       typedAttribute (const std::string& name);
187
    template <class T> const T& typedAttribute (const std::string& name) const;
188
189
    template <class T> T*       findTypedAttribute (const char name[]);
190
    template <class T> const T* findTypedAttribute (const char name[]) const;
191
192
    template <class T> T* findTypedAttribute (const std::string& name);
193
    template <class T>
194
    const T* findTypedAttribute (const std::string& name) const;
195
196
    //---------------------------------------------
197
    // Iterator-style access to existing attributes
198
    //---------------------------------------------
199
200
    typedef std::map<Name, Attribute*> AttributeMap;
201
202
    class Iterator;
203
    class ConstIterator;
204
205
    IMF_EXPORT
206
    Iterator begin ();
207
    IMF_EXPORT
208
    ConstIterator begin () const;
209
210
    IMF_EXPORT
211
    Iterator end ();
212
    IMF_EXPORT
213
    ConstIterator end () const;
214
215
    IMF_EXPORT
216
    Iterator find (const char name[]);
217
    IMF_EXPORT
218
    ConstIterator find (const char name[]) const;
219
220
    IMF_EXPORT
221
    Iterator find (const std::string& name);
222
    IMF_EXPORT
223
    ConstIterator find (const std::string& name) const;
224
225
    //--------------------------------
226
    // Access to predefined attributes
227
    //--------------------------------
228
229
    IMF_EXPORT
230
    IMATH_NAMESPACE::Box2i& displayWindow ();
231
    IMF_EXPORT
232
    const IMATH_NAMESPACE::Box2i& displayWindow () const;
233
234
    IMF_EXPORT
235
    IMATH_NAMESPACE::Box2i& dataWindow ();
236
    IMF_EXPORT
237
    const IMATH_NAMESPACE::Box2i& dataWindow () const;
238
239
    IMF_EXPORT
240
    float& pixelAspectRatio ();
241
    IMF_EXPORT
242
    const float& pixelAspectRatio () const;
243
244
    IMF_EXPORT
245
    IMATH_NAMESPACE::V2f& screenWindowCenter ();
246
    IMF_EXPORT
247
    const IMATH_NAMESPACE::V2f& screenWindowCenter () const;
248
249
    IMF_EXPORT
250
    float& screenWindowWidth ();
251
    IMF_EXPORT
252
    const float& screenWindowWidth () const;
253
254
    IMF_EXPORT
255
    ChannelList& channels ();
256
    IMF_EXPORT
257
    const ChannelList& channels () const;
258
259
    IMF_EXPORT
260
    LineOrder& lineOrder ();
261
    IMF_EXPORT
262
    const LineOrder& lineOrder () const;
263
264
    IMF_EXPORT
265
    Compression& compression ();
266
    IMF_EXPORT
267
    const Compression& compression () const;
268
269
    //-----------------------------------------------------
270
    // The header object allows one to store a compression level to be
271
    // used when writing a file.
272
    //
273
    // NB: These are NOT attributes, and will not be written to the
274
    // file, but are instead ephemeral settings to be used for this
275
    // instance of the header object.
276
    //
277
    // -----------------------------------------------------
278
    IMF_EXPORT
279
    void resetDefaultCompressionLevels ();
280
    IMF_EXPORT
281
    int& zipCompressionLevel ();
282
    IMF_EXPORT
283
    int zipCompressionLevel () const;
284
    IMF_EXPORT
285
    float& dwaCompressionLevel ();
286
    IMF_EXPORT
287
    float dwaCompressionLevel () const;
288
289
    //-----------------------------------------------------
290
    // Access to required attributes for multipart files
291
    // They are optional to non-multipart files and mandatory
292
    // for multipart files.
293
    //-----------------------------------------------------
294
    IMF_EXPORT
295
    void setName (const string& name);
296
297
    IMF_EXPORT
298
    string& name ();
299
    IMF_EXPORT
300
    const string& name () const;
301
302
    IMF_EXPORT
303
    bool hasName () const;
304
305
    IMF_EXPORT
306
    void setType (const string& Type);
307
308
    IMF_EXPORT
309
    string& type ();
310
    IMF_EXPORT
311
    const string& type () const;
312
313
    IMF_EXPORT
314
    bool hasType () const;
315
316
    IMF_EXPORT
317
    void setVersion (const int version);
318
319
    IMF_EXPORT
320
    int& version ();
321
    IMF_EXPORT
322
    const int& version () const;
323
324
    IMF_EXPORT
325
    bool hasVersion () const;
326
327
    //
328
    // the chunkCount attribute is set automatically when a file is written.
329
    // There is no need to set it manually
330
    //
331
    IMF_EXPORT
332
    void setChunkCount (int chunks);
333
    IMF_EXPORT
334
    bool hasChunkCount () const;
335
    IMF_EXPORT
336
    const int& chunkCount () const;
337
    IMF_EXPORT
338
    int& chunkCount ();
339
340
    //
341
    // for multipart files, return whether the file has a view string attribute
342
    // (for the deprecated single part multiview format EXR, see ImfMultiView.h)
343
    //
344
    IMF_EXPORT
345
    void setView (const string& view);
346
    IMF_EXPORT
347
    bool hasView () const;
348
    IMF_EXPORT
349
    string& view ();
350
    IMF_EXPORT
351
    const string& view () const;
352
353
    //----------------------------------------------------------------------
354
    // Tile Description:
355
    //
356
    // The tile description is a TileDescriptionAttribute whose name
357
    // is "tiles".  The "tiles" attribute must be present in any tiled
358
    // image file. When present, it describes various properties of the
359
    // tiles that make up the file.
360
    //
361
    // Convenience functions:
362
    //
363
    // setTileDescription(td)
364
    //     calls insert ("tiles", TileDescriptionAttribute (td))
365
    //
366
    // tileDescription()
367
    //     returns typedAttribute<TileDescriptionAttribute>("tiles").value()
368
    //
369
    // hasTileDescription()
370
    //     return findTypedAttribute<TileDescriptionAttribute>("tiles") != 0
371
    //
372
    //----------------------------------------------------------------------
373
374
    IMF_EXPORT
375
    void setTileDescription (const TileDescription& td);
376
377
    IMF_EXPORT
378
    TileDescription& tileDescription ();
379
    IMF_EXPORT
380
    const TileDescription& tileDescription () const;
381
382
    IMF_EXPORT
383
    bool hasTileDescription () const;
384
385
    //----------------------------------------------------------------------
386
    // Preview image:
387
    //
388
    // The preview image is a PreviewImageAttribute whose name is "preview".
389
    // This attribute is special -- while an image file is being written,
390
    // the pixels of the preview image can be changed repeatedly by calling
391
    // OutputFile::updatePreviewImage().
392
    //
393
    // Convenience functions:
394
    //
395
    // setPreviewImage(p)
396
    //     calls insert ("preview", PreviewImageAttribute (p))
397
    //
398
    // previewImage()
399
    //     returns typedAttribute<PreviewImageAttribute>("preview").value()
400
    //
401
    // hasPreviewImage()
402
    //     return findTypedAttribute<PreviewImageAttribute>("preview") != 0
403
    //
404
    //----------------------------------------------------------------------
405
406
    IMF_EXPORT
407
    void setPreviewImage (const PreviewImage& p);
408
409
    IMF_EXPORT
410
    PreviewImage& previewImage ();
411
    IMF_EXPORT
412
    const PreviewImage& previewImage () const;
413
414
    IMF_EXPORT
415
    bool hasPreviewImage () const;
416
417
    //-------------------------------------------------------------
418
    // Sanity check -- examines the header, and throws an exception
419
    // if it finds something wrong (empty display window, negative
420
    // pixel aspect ratio, unknown compression scheme etc...)
421
    //
422
    // set isTiled to true if you are checking a tiled/multi-res
423
    // header
424
    //-------------------------------------------------------------
425
426
    IMF_EXPORT
427
    void sanityCheck (bool isTiled = false, bool isMultipartFile = false) const;
428
429
    //----------------------------------------------------------------
430
    // Maximum image size and maximum tile size:
431
    //
432
    // sanityCheck() will throw an exception if the width or height of
433
    // the data window exceeds the maximum image width or height, or
434
    // if the size of a tile exceeds the maximum tile width or height.
435
    //
436
    // At program startup the maximum image and tile width and height
437
    // are set to zero, meaning that width and height are unlimited.
438
    //
439
    // Limiting image and tile width and height limits how much memory
440
    // will be allocated when a file is opened.  This can help protect
441
    // applications from running out of memory while trying to read
442
    // a damaged image file.
443
    //----------------------------------------------------------------
444
445
    IMF_EXPORT
446
    static void setMaxImageSize (int maxWidth, int maxHeight);
447
    IMF_EXPORT
448
    static void setMaxTileSize (int maxWidth, int maxHeight);
449
    IMF_EXPORT
450
    static void getMaxImageSize (int& maxWidth, int& maxHeight);
451
    IMF_EXPORT
452
    static void getMaxTileSize (int& maxWidth, int& maxHeight);
453
454
    //
455
    // Check if the header reads nothing.
456
    //
457
    IMF_EXPORT
458
    bool readsNothing ();
459
460
    //------------------------------------------------------------------
461
    // Input and output:
462
    //
463
    // If the header contains a preview image attribute, then writeTo()
464
    // returns the position of that attribute in the output stream; this
465
    // information is used by OutputFile::updatePreviewImage().
466
    // If the header contains no preview image attribute, then writeTo()
467
    // returns 0.
468
    //------------------------------------------------------------------
469
470
    IMF_EXPORT
471
    uint64_t writeTo (
472
        OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os,
473
        bool                                     isTiled = false) const;
474
475
    IMF_EXPORT
476
    void readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, int& version);
477
478
private:
479
    AttributeMap _map;
480
481
    bool _readsNothing;
482
};
483
484
//----------
485
// Iterators
486
//----------
487
488
class IMF_EXPORT_TYPE Header::Iterator
489
{
490
public:
491
    IMF_EXPORT
492
    Iterator ();
493
    IMF_EXPORT
494
    Iterator (const Header::AttributeMap::iterator& i);
495
496
    IMF_EXPORT
497
    Iterator& operator++ ();
498
    IMF_EXPORT
499
    Iterator operator++ (int);
500
501
    IMF_EXPORT
502
    const char* name () const;
503
    IMF_EXPORT
504
    Attribute& attribute () const;
505
506
private:
507
    friend class Header::ConstIterator;
508
509
    Header::AttributeMap::iterator _i;
510
};
511
512
class IMF_EXPORT_TYPE Header::ConstIterator
513
{
514
public:
515
    IMF_EXPORT
516
    ConstIterator ();
517
    IMF_EXPORT
518
    ConstIterator (const Header::AttributeMap::const_iterator& i);
519
    IMF_EXPORT
520
    ConstIterator (const Header::Iterator& other);
521
522
    IMF_EXPORT
523
    ConstIterator& operator++ ();
524
    IMF_EXPORT
525
    ConstIterator operator++ (int);
526
527
    IMF_EXPORT
528
    const char* name () const;
529
    IMF_EXPORT
530
    const Attribute& attribute () const;
531
532
private:
533
    friend bool operator== (const ConstIterator&, const ConstIterator&);
534
    friend bool operator!= (const ConstIterator&, const ConstIterator&);
535
536
    Header::AttributeMap::const_iterator _i;
537
};
538
539
//------------------------------------------------------------------------
540
// Library initialization:
541
//
542
// In a multithreaded program, staticInitialize() must be called once
543
// during startup, before the program accesses any other functions or
544
// classes in the OpenEXR library.  Calling staticInitialize() in this
545
// way avoids races during initialization of the library's global
546
// variables.
547
//
548
// Single-threaded programs are not required to call staticInitialize();
549
// initialization of the library's global variables happens automatically.
550
//
551
//------------------------------------------------------------------------
552
553
IMF_EXPORT void staticInitialize ();
554
555
//-----------------
556
// Inline Functions
557
//-----------------
558
559
inline Header::Iterator::Iterator () : _i ()
560
{
561
    // empty
562
}
563
564
inline Header::Iterator::Iterator (const Header::AttributeMap::iterator& i)
565
    : _i (i)
566
{
567
    // empty
568
}
569
570
inline Header::Iterator&
571
Header::Iterator::operator++ ()
572
0
{
573
0
    ++_i;
574
0
    return *this;
575
0
}
576
577
inline Header::Iterator
578
Header::Iterator::operator++ (int)
579
0
{
580
0
    Iterator tmp = *this;
581
0
    ++_i;
582
0
    return tmp;
583
0
}
584
585
inline const char*
586
Header::Iterator::name () const
587
0
{
588
0
    return *_i->first;
589
0
}
590
591
inline Attribute&
592
Header::Iterator::attribute () const
593
0
{
594
0
    return *_i->second;
595
0
}
596
597
inline Header::ConstIterator::ConstIterator () : _i ()
598
{
599
    // empty
600
}
601
602
inline Header::ConstIterator::ConstIterator (
603
    const Header::AttributeMap::const_iterator& i)
604
    : _i (i)
605
{
606
    // empty
607
}
608
609
inline Header::ConstIterator::ConstIterator (const Header::Iterator& other)
610
    : _i (other._i)
611
{
612
    // empty
613
}
614
615
inline Header::ConstIterator&
616
Header::ConstIterator::operator++ ()
617
0
{
618
0
    ++_i;
619
0
    return *this;
620
0
}
621
622
inline Header::ConstIterator
623
Header::ConstIterator::operator++ (int)
624
0
{
625
0
    ConstIterator tmp = *this;
626
0
    ++_i;
627
0
    return tmp;
628
0
}
629
630
inline const char*
631
Header::ConstIterator::name () const
632
0
{
633
0
    return *_i->first;
634
0
}
635
636
inline const Attribute&
637
Header::ConstIterator::attribute () const
638
{
639
    return *_i->second;
640
}
641
642
inline bool
643
operator== (const Header::ConstIterator& x, const Header::ConstIterator& y)
644
0
{
645
0
    return x._i == y._i;
646
0
}
647
648
inline bool
649
operator!= (const Header::ConstIterator& x, const Header::ConstIterator& y)
650
0
{
651
0
    return !(x == y);
652
0
}
653
654
//---------------------
655
// Template definitions
656
//---------------------
657
658
template <class T>
659
T&
660
Header::typedAttribute (const char name[])
661
{
662
    Attribute* attr  = &(*this)[name];
663
    T*         tattr = dynamic_cast<T*> (attr);
664
665
    if (tattr == 0) throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
666
667
    return *tattr;
668
}
669
670
template <class T>
671
const T&
672
Header::typedAttribute (const char name[]) const
673
{
674
    const Attribute* attr  = &(*this)[name];
675
    const T*         tattr = dynamic_cast<const T*> (attr);
676
677
    if (tattr == 0) throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type.");
678
679
    return *tattr;
680
}
681
682
template <class T>
683
T&
684
Header::typedAttribute (const std::string& name)
685
{
686
    return typedAttribute<T> (name.c_str ());
687
}
688
689
template <class T>
690
const T&
691
Header::typedAttribute (const std::string& name) const
692
{
693
    return typedAttribute<T> (name.c_str ());
694
}
695
696
template <class T>
697
T*
698
Header::findTypedAttribute (const char name[])
699
{
700
    AttributeMap::iterator i = _map.find (name);
701
    return (i == _map.end ()) ? 0 : dynamic_cast<T*> (i->second);
702
}
703
704
template <class T>
705
const T*
706
Header::findTypedAttribute (const char name[]) const
707
50.9k
{
708
50.9k
    AttributeMap::const_iterator i = _map.find (name);
709
50.9k
    return (i == _map.end ()) ? 0 : dynamic_cast<const T*> (i->second);
710
50.9k
}
Imf_3_3::TypedAttribute<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const* Imf_3_3::Header::findTypedAttribute<Imf_3_3::TypedAttribute<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > >(char const*) const
Line
Count
Source
707
4.86k
{
708
4.86k
    AttributeMap::const_iterator i = _map.find (name);
709
4.86k
    return (i == _map.end ()) ? 0 : dynamic_cast<const T*> (i->second);
710
4.86k
}
Imf_3_3::TypedAttribute<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const* Imf_3_3::Header::findTypedAttribute<Imf_3_3::TypedAttribute<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(char const*) const
Line
Count
Source
707
37.3k
{
708
37.3k
    AttributeMap::const_iterator i = _map.find (name);
709
37.3k
    return (i == _map.end ()) ? 0 : dynamic_cast<const T*> (i->second);
710
37.3k
}
Imf_3_3::TypedAttribute<float> const* Imf_3_3::Header::findTypedAttribute<Imf_3_3::TypedAttribute<float> >(char const*) const
Line
Count
Source
707
6.37k
{
708
6.37k
    AttributeMap::const_iterator i = _map.find (name);
709
6.37k
    return (i == _map.end ()) ? 0 : dynamic_cast<const T*> (i->second);
710
6.37k
}
Imf_3_3::TypedAttribute<Imf_3_3::Chromaticities> const* Imf_3_3::Header::findTypedAttribute<Imf_3_3::TypedAttribute<Imf_3_3::Chromaticities> >(char const*) const
Line
Count
Source
707
2.36k
{
708
2.36k
    AttributeMap::const_iterator i = _map.find (name);
709
2.36k
    return (i == _map.end ()) ? 0 : dynamic_cast<const T*> (i->second);
710
2.36k
}
711
712
template <class T>
713
T*
714
Header::findTypedAttribute (const std::string& name)
715
{
716
    return findTypedAttribute<T> (name.c_str ());
717
}
718
719
template <class T>
720
const T*
721
Header::findTypedAttribute (const std::string& name) const
722
{
723
    return findTypedAttribute<T> (name.c_str ());
724
}
725
726
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
727
728
#endif